|
|
User login
Feeds |
CMdaAudioRecorderUtility - last second cut off
|
|||||
| Thu, 2004-11-25 13:26 | |
|
|
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 -- |
Forum posts: 45
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!
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
Forum posts: 45
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.
{
// 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!
Forum posts: 45
Good luck
Kibi
--
Kibi
Give me immortality - or give me death!