CMdaAudioRecorderUtility - last second cut off

Login to reply to this topic.
Thu, 2004-11-25 13:26
Joined: 2003-10-08
Forum posts: 45
Hi  - I'm using CMdaAudioRecorderUtility on a 6600 to record a phone call.

I basically start recording when the call begins and want to record up until the end of the call.

Here's the start of the problem: CMdaAudioRecorderUtility crops the last second when you  stop recording. (I thought I saw this on a "Known Issues" list, though I can't find it now). Anyway, the solution should be to record for one more second after the call finishes...

Here's the real problem - when the call ends, the CMdaAudioRecorderUtility stops recording - it calls back to MoscoStateChangeEvent with an error "-13" which means KErrDied. I don't get the chance to continue recording for an extra second, even if I want to.

So - all my recorded phone calls have about a second cut off the end.

Does anyone have a solution to this problem? Any method of attack would be good - either a fix for the cropping or a fix for the dying when the call ends (or anything else you can think of)

Thanks

Kibi

--
Kibi
Give me immortality - or give me death!


Mon, 2004-11-29 15:37
Joined: 2003-10-08
Forum posts: 45
CMdaAudioRecorderUtility - last second cut off
Replying to my own post!

It turns out that pretty much the entire phone conversation is correctly caught in the recorded WAV file - however, the built in 6600 Voice Recorder application does not play the file correctly - when I sent the file to my PC I could hear the last second which was previously "Cut off"!

So why doesn't the sound get played? I found 2 reasons:
Looking inside the WAV file which had been created, the length of the data chunk was incorrectly short - it seems most Windows players don't care what the data length is officially and play to the end (probably because they are "protecting" against buffer overwrite hacks, so they simply don't worry what the stated length is). The Symbian player might possibly be more strict, so I adjusted the file (after recording) to have this length correct.

This step helped a bit, but not completely - I could still hear more on my PC than my phone from the same file....so I then adjusted the file adding another second of blank sound on the end of the file (also adjusting the file data length and data chunk length in the file). This gives me the full amount of sound info playing on the phone that I had on the PC.

Still, it's a ridiculous hack, and I wonder when Nokia/Symbian will get around to fixing the sound player utility.

Also, if anyone has information about recording *past* the end of the call (I'm still losing maybe half a second of conversation, and while that half second is normally "Goodb..." it still sounds a little awkward) it would be great to hear it.

thanks

Kibi

--
Kibi
Give me immortality - or give me death!

Tue, 2004-12-14 06:02
prashanta.halder (not verified)
Forum posts: 2043
Recording from Incoming voice channel
Hi Kibi

I am also trying the same, can u share the code?

Also i wanted to know that while recording was you able to hear the incoming voice in the speaker?

Feedback will be greatly appreciated
Tue, 2004-12-14 11:04
Joined: 2003-10-08
Forum posts: 45
Small code snippets for fix to sound bug
Here you go Cheezy
I call this function after I finish the recording.  That is, I call Stop() on the
CMdaAudioRecorderUtility object, and then Close(), then I call this:

Disclaimer: This code is just an example, provided "as-is" with no guarantee that it won't blow up your house or steal your girlfriend. It absolutely will NOT compile for you since it uses a couple of our home-made classes. Still you should get the idea.

by the way, I'm aware there are some glaring inefficiencies in theis code but at least it's fairly clear. If you see a real problem (such as potential leaks) I'd love to hear.

iNewFileName is the name (full path) of the file I just recorded.

Code:
void CRecorderAdapter::AddBlankSecondL()
{
   // In order to read in data in the correct littleEndian fashion,
   // we have our own cool little class. This code will not compile
   // for you but bear in mind that when you read in bytes from a
   // file you have to make sure they are interpreted correctly before
   // blindly casting to your type. Anyway, the point is the class used
   // here CIntelDataReadBuffer is not something you will find in the SDK
   CIntelDataReadBuffer* reader = CIntelDataReadBuffer::NewL(100);
   CleanupStack::PushL(reader);
   RFs fs = CCoeEnv::Static()->FsSession();
   RFile file;
   TInt ret1 = file.Open(fs, iNewFileName, EFileWrite);
   if (ret1 == KErrNone)
   {
       CleanupClosePushL(file);
       TBuf8<4> sizeBuf;

       TBuf8<4> id; //four bytes to hold 'RIFF'
       file.Read(id); //read in first four bytes
       if (id.Compare(_L8("RIFF")) == 0)
       { //we had 'RIFF' let's continue
           //we want the size to be 4k bigger than it was
           //so take the size of the file, add 4k then take
           //off 8 for the RIFF and length of the int
           TInt fileSize = 0;
           file.Size(fileSize);

           TInt newSize = fileSize + (4096 - 8);

           // now you have to do a little bit of magic to write an int (4 bytes)
           // into a buffer in the correct littleEndian format. This is left as
           // an exercise for the reader! We have our own little class for it:
           // our class is CIntelDataWriteBuffer so obviously this won't
           // compile for you...
           CIntelDataWriteBuffer* writer = CIntelDataWriteBuffer::NewL(4);
           CleanupStack::PushL(writer);
           writer->WriteIntL(newSize);

           HBufC8* buffer = writer->GetBufferL(); // Passes ownership
           CleanupStack::PushL(buffer);
           file.Write(*buffer, 4);
           CleanupStack::PopAndDestroy(); //buffer
           CleanupStack::PopAndDestroy(); //writer

           //read in 4 byte string now
           file.Read(id); //read in next four bytes
           if (id.Compare(_L8("WAVE")) == 0)
           { //this is probably a wave file since it contained "WAVE"
               file.Read(id); //read in 4 bytes "fmt "; (I think)

               //now we need to loop through until we find the "data"
               //block - the general structure is 4 bytes name, 4 bytes
               //length and then the length bytes of stuff.
               //It turns out the files recorded on Symbian seem to have
               //the data length wrong, so we also need to find the "data"
               //block and then adjust the length
               while (id.Compare(_L8("data")) != 0)
               {
                   file.Read(sizeBuf); //this is the length
                   // using our magic reader class
                   reader->Reset();
                   reader->AddDataL(sizeBuf);
                   TInt32 length = 0;
                   reader->ReadInt(length);
                   //this seek should take us to the end of the block
                   TInt lengthInt = length;
                   file.Seek(ESeekCurrent, lengthInt);

                   file.Read(id);
               }
               //when we get here we must have found the "data" block
               //so now read the length of the block (as given)
               file.Read(sizeBuf); //this is the length
               reader->Reset();
               reader->AddDataL(sizeBuf);
               TInt32 dataLength = 0;
               reader->ReadInt(dataLength);
               TInt pos = -4;
               file.Seek(ESeekCurrent, pos);
               //now pos should contain the pos of the length
               //our length should be set to the size of the file
               // plus 4K minus (this pos plus four)
               TInt newDataLength = fileSize + 4096 - (pos + 4);

               writer = CIntelDataWriteBuffer::NewL(4);
               CleanupStack::PushL(writer);
               writer->WriteIntL(newDataLength);

               buffer = writer->GetBufferL(); // Passes ownership
               CleanupStack::PushL(buffer);
               file.Write(*buffer, 4);
               CleanupStack::PopAndDestroy(); //buffer
               CleanupStack::PopAndDestroy(); //writer

               //now we have to add that 4K of data
               //now go to end
               pos = 0;
               file.Seek(ESeekEnd, pos);

               writer = CIntelDataWriteBuffer::NewL(4096);
               CleanupStack::PushL(writer);
               //fill the buffer with 4k blanks
               for (TInt i = 0; i < 1024; i++)
               {
                 writer->WriteIntL(0);
               }

               buffer = writer->GetBufferL(); // Passes ownership
               CleanupStack::PushL(buffer);
               /*TInt ret = */file.Write(*buffer, 4096);
               CleanupStack::PopAndDestroy(); //buffer
               CleanupStack::PopAndDestroy(); //writer


               file.Flush();
           }
           else
           {
                 DoLog(_L("Error: RIFF file but not a wave file"));
           }
       }
       else
       {
             DoLog(_L("Error: not a RIFF file"));
       }
       //instead of this
       //file.Close();
       //do this
       CleanupStack::PopAndDestroy(); //file.Close()
   }
   CleanupStack::PopAndDestroy(); //reader
}

Notes - I'm adding 4k of blank space because empirically I observed that 1 minute of WAV recording made a file approximately 240k long and so 1/60 of that is 4k. The implication is that each 4bits is one frame of mono sound, assuming a 8000 Hz sample rate, It wasn't clear form the documentation I read, but it seems to work.

--
Kibi
Give me immortality - or give me death!

Tue, 2004-12-14 11:09
Joined: 2003-10-08
Forum posts: 45
CMdaAudioRecorderUtility - last second cut off
Oh yeah, and in answer to your other question, I can hear the incoming voice while I am recording - this is basically an app for recording phone conversations. The recorder has the unfortunate (I think) feature that there is a little "beep" on the line every 5 seconds. This seems to be added by Nokia, perhaps to forestall legal issues since in some states it is illegal to record a conversation without both parties being aware of the fact. Caveat codor (or whatever).

Good luck

Kibi

--
Kibi
Give me immortality - or give me death!

  • Login to reply to this topic.