When it comes to beInitStream() it says:
BE_ERR beInitStream(
// Pointer at the struct containing encoder settings.
PBE_CONFIG pbeConfig,
// Pointer at double word where number of samples to send to each
beEncodeChunk() is returned.
PDWORD dwSamples,
// Pointer at double word where minimum size in bytes of output buffer is
returned.
PDWORD dwBufferSize,
// Pointer at integer where Stream handle is returned.
PHBE_STREAM phbeStream
)
So, I should do something like this:
BE_CONFIG beConfig; // then I populate beConfig.(...)
HBE_STREAM hbeStream = 0;
DWORD dwSamples = 0;
DWORD dwMP3Buffer = 0;
beInitStream(&beConfig, &dwSamples, &dwMP3Buffer, &hbeStream);
Now, I wonder if I can take no notice of the "dwSamples" value returned,
that's because I am doing real-time endless encoding and I though I would
encode like this:
// 88200 Bytes = 44100 x 2 (Stereo) , 1 second of WAVE audio
so I am like in a: while( dwRead = getWaveChunk(pWavBuffer) > 0 ) where
"dwRead" will be always 88200!
Can it actually be done? for instance:
PBYTE pMP3Buffer = new BYTE[dwMP3Buffer];
DWORD dwRead = 0;
DWORD dwWrite = 0;
while( dwRead = getWaveChunk(pWavBuffer) > 0 )
{
beEncodeChunk( hbeStream, dwRead, pWAVBuffer, pMP3Buffer, &dwWrite );
// pWAVBuffer contains the WAVE chunk
// pMP3Buffer contains the MP3 encodec chunk
}
where:
beEncodeChunk(
//Handle of the stream.
HBE_STREAM hbeStream,
//Number of samples to be encoded for this call. This should be identical
to what is returned by beInitStream()!
DWORD nSamples,
//Pointer at the 16-bit signed samples to be encoded. These should be in
stereo when encoding a stereo MP3
PSHORT pSamples,
//Where to write the encoded data. This buffer should be at least of the
minimum size returned by beInitStream().
PBYTE pOutput,
//Where to return number of bytes of encoded data written. The amount of
data written might vary from chunk to chunk.
PDWORD pdwOutput
)
So can I force the lame to encode 88200 Bytes at a time?
thanks
I am going to do real time encoding while capturing audio with the waveForm
API I was wondering wheter I myself could supply the dwSamples value to the
function:
beInitStream(&bec, &dwSamples, &dwBufferSize, &hbe);
that's beacuse I would like to encode 88200 Bytes of wav at a time! (88200
is 44100 x 2, so, 1 second of audio stereo!)
when I try to read the values return by the beInitStream() function I get:
dwSamples: 2304
dwBufferSize: 8640 (mp3 buffer size)
By the way, what is dwsamples??
thanks
> When it comes to beInitStream() it says:
>
> BE_ERR beInitStream(
>
> // Pointer at the struct containing encoder settings.
> PBE_CONFIG pbeConfig,
>
> // Pointer at double word where number of samples to send to each
> beEncodeChunk() is returned.
> PDWORD dwSamples,
>
> // Pointer at double word where minimum size in bytes of output buffer is
> returned.
> PDWORD dwBufferSize,
>
> // Pointer at integer where Stream handle is returned.
> PHBE_STREAM phbeStream
> )
>
> So, I should do something like this:
>
> BE_CONFIG beConfig; // then I populate beConfig.(...)
> HBE_STREAM hbeStream = 0;
> DWORD dwSamples = 0;
> DWORD dwMP3Buffer = 0;
>
> beInitStream(&beConfig, &dwSamples, &dwMP3Buffer, &hbeStream);
// Define WAVEFORMATEX Structure:
WAVEFORMATEX wf;
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.wBitsPerSample = 16;
wf.nChannels = 2
wf.nSamplesPerSec = 44100
wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) / 8;
wf.nAvgBytesPerSec = (wf.nSamplesPerSec * wf.nBlockAlign);
//
This mean "nAvgBytesPerSec" will be (DWORD) 176400 Bytes (per second)
My application does real time capturing from a given source and notify me
thru a CALLBACK_EVENT when the (LPBYTE) buffer[176400] is filled and return
the buffer:
while(1)
{
// CALLBACK EVENT
WaitForSingleObject(hevent, INFINITE);
// sizeof(buffer) = 176400
// encode buffer
}
The code above is the barebones of my capturing & encoding programm! On the
other hand, I have found out that the Lame-enc DLL returns me some values
telling me how many samples it is willing to encode when I first init it!
PBYTE pMP3Buffer =NULL;
PSHORT pWAVBuffer =NULL;
beInitStream(&beConfig, &dwSamples, &dwMP3Buffer, &hbeStream);
// Allocate MP3 buffer
pMP3Buffer = new BYTE[dwMP3Buffer]; // (dword) 8640
// Allocate WAV buffer
pWAVBuffer = new SHORT[dwSamples]; // (dword) 2304
whereas 2304 is too little for me! Also, 176400 / 2304 = 76,56 as I don't
really get it!
I have found some code on the internet to show how to use the DLL to encode
a WAVE file. What the code basically does it the following:
// Convert All PCM samples
while ( (dwRead = fread(pWAVBuffer,sizeof(SHORT),dwSamples,pFileIn)) > 0 )
{
// Encode samples
beEncodeChunk(hbeStream, dwRead, pWAVBuffer, pMP3Buffer, &dwWrite);
// Save chunk
fwrite(pMP3Buffer,1,dwWrite,pFileOut);
}
It basically reads "dwSamples" in "pWAVBuffer" and sends it to the
encoder...
I am really stuck at this. I wish I could push as many samples as I want!
(176400)
thanks
I don't know anything about Lame, but with wave
operations it is normal to have multiple buffers,
typically 3 or more. That way you can have one
filling, one waiting to be filled, and one being
processed.
It's not clear why you want *exactly* 176400 bytes
in your buffer, but if this is indeed a
requirement for some reason, you could use enough
smaller buffers to exceed 176400 total bytes, then
treat it like a circular buffer when using 176400
bytes at a time. This might require some pointer
manipulations and breaking the transfer into 2
chunks. Why not just use some multiple of 2304
bytes?
Best regards,
Bob Masta
DAQARTA v5.00
Data AcQuisition And Real-Time Analysis
www.daqarta.com
Scope, Spectrum, Spectrogram, Sound Level Meter
Frequency Counter, FREE Signal Generator
Pitch Track, Pitch-to-MIDI
DaqMusic - FREE MUSIC, Forever!
(Some assembly required)
Science (and fun!) with your sound card!
> It's not clear why you want *exactly* 176400 bytes
> in your buffer, but if this is indeed a
> requirement for some reason, you could use enough
> smaller buffers to exceed 176400 total bytes, then
> treat it like a circular buffer when using 176400
> bytes at a time. This might require some pointer
> manipulations and breaking the transfer into 2
> chunks. Why not just use some multiple of 2304
> bytes?
Hi,
for some reason the Lame-enc DLL will only accept 2304 Samples (Stereo:
2x1152) at a time. I cannot set the wave encoder buffer to 2304 bytes, even
if I push 77 buffers:
2304 x 77 = 177408 (>176400)
This because the sound will be choppy (suck) I tried that over and over...
All I can do is set up a buffer of 176400 Bytes OR I can always push 30
buffers of 5880 each! (I love this last one, I do get perfect sound!) Also
5880 is really a small chuck.
So, when I get signalized the buffer is filled (5880 bytes) I will have to
encode the WAVE buffer to MP3 by calling the beEncodeChunk() function, say 3
times in order to pass it a part of the buffer say:
2304 bytes, 2304 bytes and 1272 bytes = 5880 bytes!
Now, how can I do this? I should substr the buffer...
this is the event loop:
while(1)
{
// CALLBACK EVENT
WaitForSingleObject(hevent, INFINITE);
if(buff[k].dwFlags & WHDR_DONE)
{
//buff[k].lpData is 5880 Bytes long...
while(...)
{
//encode();
}
waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR));
}
if(k == num_buffers -1)
k=0;
else
k++;
}
thanks
> All I can do is set up a buffer of 176400 Bytes OR I can always push 30
> buffers of 5880 each! (I love this last one, I do get perfect sound!) Also
> 5880 is really a small chuck.
I would like to move this form reading from a file to reading from that
buffer (5880)
// Init the MP3 Stream
beInitStream(&bec, &dwSamples, &dwMP3Buffer, &hbeStream);
// Allocate MP3 buffer
PBYTE pMP3Buffer = new BYTE[dwMP3Buffer];
// Allocate WAV buffer
PSHORT pWAVBuffer = new SHORT[dwSamples];
// Convert All PCM samples
while ( ( dwRead = fread(pWAVBuffer, sizeof(SHORT), dwSamples, pFileIn)) >
0 )
{
// Encode samples
beEncodeChunk(hbeStream, dwRead, pWAVBuffer, pMP3Buffer, &dwWrite);
// write dwWrite bytes that are returned in tehe pMP3Buffer to disk
fwrite(pMP3Buffer,1,dwWrite,pFileOut) != dwWrite)
}
If the DLL will only accept 2304 samples at a time then why don't you
just make your wave buffer some multiple of this, as large as you
like? Then for each WAV buffer that is completed you would execute a
little loop to call the DLL several times until the entire WAV buffer
has been converted, passing it 2304 samples each time around the loop.
> If the DLL will only accept 2304 samples at a time then why don't you
> just make your wave buffer some multiple of this, as large as you
> like? Then for each WAV buffer that is completed you would execute a
> little loop to call the DLL several times until the entire WAV buffer
> has been converted, passing it 2304 samples each time around the loop.
I'll be encoding 2304 at a time!
Now, I have problems encoding the data form the WAVEform API (internal mic)
I thought I would try to use the same code I used to encode an mp3 from a
WAVE file as shown below:
***********
// BE_ERR beInitStream( PBE_CONFIG pbeConfig,
PDWORD dwSamples,
PDWORD dwBufferSize,
PHBE_STREAM phbeStream );
// BE_ERR beEncodeChunk( HBE_STREAM hbeStream,
DWORD nSamples,
PSHORT pSamples,
PBYTE pOutput,
PDWORD pdwOutput );
// Init the MP3 Stream
beInitStream(&bec, &dwSamples, &dwMP3Buffer, &hbeStream);
// Allocate MP3 buffer
pMP3Buffer = new BYTE[dwMP3Buffer];
// Allocate WAV buffer
pWAVBuffer = new SHORT[dwSamples];
// dwSamples = 2304, dwRead ritorna 2304
while ( ( dwRead = fread(pWAVBuffer, sizeof(SHORT), dwSamples, pFileIn)) >
0 )
{
// Encode samples
beEncodeChunk(hbeStream, dwRead, pWAVBuffer, pMP3Buffer, &dwWrite);
// Write dwWrite bytes that are returned in tehe pMP3Buffer to disk
fwrite(pMP3Buffer, 1, dwWrite, pFileOut);
}
**********
So I went like this:
**********
// dwSamples is 2304
// buff[k].lpData is 6912 bytes long (LPSTR)
// I'm gonna read it 2304 bytes at a time (3 times)
// then store its value in PSHORT pWAVChunk = new SHORT[dwSamples]
// Loop...
int dwChunkSeek = 0;
int dwLoop = 0;
int k = 0;
while(1)
{
// CALLBACK EVENT
WaitForSingleObject(hevent, INFINITE);
if(buff[k].dwFlags & WHDR_DONE)
{
// Encode chunk by chunk
while(dwLoop < 3)
{
// copy part of the buffer
memcpy(pWAVChunk, buff[k].lpData + dwChunkSeek, 2304);
// Encode samples
beEncodeChunk(hbeStream, 2304, pWAVChunk, pMP3Buffer,&dwWrite);
// Save
hFile.write((LPSTR)pMP3Buffer, dwWrite);
dwChunkSeek += 2304;
++dwLoop;
}
dwLoop = 0;
dwChunkSeek = 0;
waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR));
}
}
***********
but I get a bad mp3 file with noise only...
probably I got something wrong here:
memcpy(pWAVChunk, buff[k].lpData + dwChunkSeek, 2304);
or here?
beEncodeChunk(hbeStream, 2304, pWAVChunk, pMP3Buffer,&dwWrite);
thanks
Yea, looks like it.
sizeof(char) is 1
sizeof(short) is 2
lpData is a char*, so adding 2304 increments it by 2304 bytes. But
the data it is really pointing at is an array of shorts. So to
increment lpData by 2304 shorts you need to add 2*2304 = 4608.
> lpData is a char*, so adding 2304 increments it by 2304 bytes. But
> the data it is really pointing at is an array of shorts. So to
> ncrement lpData by 2304 shorts you need to add 2*2304 = 4608.
I'm sorry, that is not working either...do you think I should cast? what I
dont get is the following
// dwSamples = 2304;
dwRead = fread(pWAVBuffer, sizeof(SHORT), dwSamples, pFileIn));
basically that is reading sizeof(SHORT)*dwSamples (4608). Yet, dwRead is
2304...
I record the same time a WAVE and MP3 file, this is the main code for my
project:
while(1)
{
if(stop_thread_flag)
break;
// CALLBACK EVENT
WaitForSingleObject(hevent, INFINITE);
if(buff[k].dwFlags & WHDR_DONE && !stop_thread_flag)
{
// Save WAVE
hFile2.write(buff[k].lpData, buff[k].dwBytesRecorded);
dwWAVBufferCounter += buff[k].dwBytesRecorded;
// Encode chunk by chunk (dwLoop = 0)
while(dwLoop <= 3)
{
// copy part of the buffer...PSHORT pWAVChunk = new SHORT[dwSamples]
memcpy(pWAVChunk, buff[k].lpData + dwChunkSeek*sizeof(SHORT), 2304);
// Encode samples
result = beEncodeChunk(hbeStream, 2304, pWAVChunk, pMP3Buffer,
&dwWrite);
//printf("%d -> %d \n", hashChunk[dwLoop], dwWrite);
// Save MP3
hFile.write((LPSTR)pMP3Buffer, dwWrite);
dwChunkSeek += 2304;
dwMP3BufferCounter += dwWrite;
++dwLoop;
}
dwLoop = 0;
dwChunkSeek = 0;
waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR));
}
if(k == num_buffers -1)
k = 0;
else
k++;
}
I am really stuck at that :-(
> I am really stuck at that :-(
Great! I seem to have sorted it out like this:
int k = 0;
while(1)
{
if(stop_thread_flag)
break;
// CALLBACK EVENT
WaitForSingleObject(hevent, INFINITE);
if(buff[k].dwFlags & WHDR_DONE && !stop_thread_flag)
{
// Save WAVE
hFile2.write(buff[k].lpData, buff[k].dwBytesRecorded);
dwWAVBufferCounter += buff[k].dwBytesRecorded;
// Encode samples
//
// (LPSTR) buff[k].lpData is (system_buf_len) bytes long (8 BIT)
// (PSHORT)buff[k].lpData is (system_buf_len)/2 (16 BIT)
//
result = beEncodeChunk(hbeStream, dwSamples, (PSHORT)buff[k].lpData,
pMP3Buffer, &dwWrite);
// Save MP3
hFile.write((LPSTR)pMP3Buffer, dwWrite);
dwMP3BufferCounter += dwWrite;
That's what it should do. fread returns the number of "items" read,
where the 2nd parameter is the size of an "item".
>
> I record the same time a WAVE and MP3 file, this is the main code for my
> project:
>
> while(1)
> {
> if(stop_thread_flag)
> break;
> // CALLBACK EVENT
> WaitForSingleObject(hevent, INFINITE);
>
> if(buff[k].dwFlags & WHDR_DONE && !stop_thread_flag)
> {
> // Save WAVE
> hFile2.write(buff[k].lpData, buff[k].dwBytesRecorded);
> dwWAVBufferCounter += buff[k].dwBytesRecorded;
>
> // Encode chunk by chunk (dwLoop = 0)
> while(dwLoop <= 3)
> {
> // copy part of the buffer...PSHORT pWAVChunk = new SHORT[dwSamples]
> memcpy(pWAVChunk, buff[k].lpData + dwChunkSeek*sizeof(SHORT), 2304);
>
> // Encode samples
> result = beEncodeChunk(hbeStream, 2304, pWAVChunk, pMP3Buffer,
> &dwWrite);
>
> //printf("%d -> %d \n", hashChunk[dwLoop], dwWrite);
> // Save MP3
> hFile.write((LPSTR)pMP3Buffer, dwWrite);
> dwChunkSeek += 2304;
> dwMP3BufferCounter += dwWrite;
> ++dwLoop;
> }
This loop runs 4 times. But your earlier post says 3 is what you
intend. Be careful!
> dwLoop = 0;
> dwChunkSeek = 0;
> waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR));
> }
> if(k == num_buffers -1)
> k = 0;
> else
> k++;
>
> }
>
> I am really stuck at that :-(
Don't know which "that" you mean, and you didn't say what's wrong.
> Great! I seem to have sorted it out like this:
basically I get the audio thru the WAVFORM API to a 2304*2 bytes long buffer
(LPSTR),
so that when I do (PSHORT)buffer to the DLL it'll look like 2304 samples (16
BIT)
having said that, I am getting mono audio...
the whole code is avaible here:
http://theartofweb.net/cpp/mp3Recorder_05.txt
the programm is supposed to grab the audi from a device and save it realtime
in both WAVE and MP3 files