Author Topic: [VC++] Recording left and right channels in two mp3 files  (Read 4415 times)

DriMarq

  • Guest
Hi friends, I'm new in this forum. I'm trying to record data from the left and right channel and save them in two mp3 files... I already read some docs and some posts regarding this issue, but I'm still a bit confused about that. Please, could anybody help me to fix the following code to accomplish that?

Code: [Select]
HRECORD channelRec;
HSTREAM channel_L;
HSTREAM channel_R;


DWORD CALLBACK DummyStreamProc(HSTREAM handle, void *buffer, DWORD length, DWORD user)
{
   return length;
}


BOOL CALLBACK RecordProc(HRECORD handle, void *buf, DWORD len, DWORD user)
{
   short *stereo = (short*)buf;
   short *left;
   short *right;

   left = (short*)malloc(len/2);      // allocate buffer for left channel
   right = (short*)malloc(len/2);     // allocate buffer for right channel

   for ( int i=0 ; i < len/4 ; i++ )
   {
      left[i]  = stereo[i*2];
      right[i] = stereo[i*2+1];
   }

   BASS_ChannelGetData(leftencoder, left, len/2); // feed left channel to encoder
   BASS_ChannelGetData(rightencoder,right,len/2); // feed right channel to encoder

   free(left);
   free(right);

   return TRUE;
}


HRESULT InitBASS()
{
   // check the correct BASS was loaded
   if ( HIWORD(BASS_GetVersion()) != BASSVERSION )
   {
      MessageBox(0,"An incorrect version of BASS.DLL was loaded",0,MB_ICONERROR);
      return E_FAIL;
   }

   // initialize BASS recording (default device)
   if ( !BASS_RecordInit(-1) )
   {
      MessageBox(0,"Can't initialize device",0,MB_ICONERROR);
      return E_FAIL;
   }

   // start recording (44100hz, stereo, 16-bit)
   if ( !( channelRec = BASS_RecordStart(44100,2,0,(RECORDPROC*)&RecordProc,0) ) )
   {
      MessageBox(0,"Can't start recording",0,MB_ICONERROR);
      return E_FAIL;
   }

   // Start encoding
   BASS_CHANNELINFO i;
   BASS_ChannelGetInfo(channelRec,&i);

   channel_L  = BASS_StreamCreate( i.freq,1, i.flags|BASS_STREAM_DECODE, DummyStreamProc, 0 );
   channel_R  = BASS_StreamCreate( i.freq,1, i.flags|BASS_STREAM_DECODE, DummyStreamProc, 0 );

   BASS_Encode_Start(channel_L, "lame --alt-preset standard - outputL.mp3", 0, NULL, 0);
   BASS_Encode_Start(channel_R, "lame --alt-preset standard - outputR.mp3", 0, NULL, 0);
   BASS_ChannelPlay(channel_L,0);
   BASS_ChannelPlay(channel_R,0);

   return S_OK;
}


VOID StopRecording()
{
   BASS_ChannelStop(channelRec);

   BASS_StreamCreateFile(FALSE,"outputL.mp3",0,0,0);
   BASS_StreamCreateFile(FALSE,"outputR.mp3",0,0,0);
}

Thanks in advance

Ian @ un4seen

  • Administrator
  • Posts: 20437
That basically looks ok, but you need to stop the encoders and free the dummy streams. Or just free the streams, and add the BASS_ENCODE_AUTOFREE flag to the BASS_Encode_Start calls.

Btw, you can also now replace the "DummyStreamProc" with "NULL" in the BASS_StreamCreate calls, and the BASS_ChannelPlay calls aren't needed :)

DriMarq

  • Guest
Ian @ un4seen, thank you much for replying. Although the examples in the BASS docs are in C, I noticed few people here using this language. Most use Delphi and VB.  :)

OK, back to issue, I did the changes you suggested, but the code doesn't still work (the mp3 files are not generated).  :( It perfectly works with WAV (no encoders) and with WMA.

It follows the code:

Code: [Select]
HRECORD channelRec;
HSTREAM channel_L;
HSTREAM channel_R;


BOOL CALLBACK RecordProc(HRECORD handle, void *buf, DWORD len, DWORD user)
{
   short *stereo = (short*)buf;
   short *left;
   short *right;

   left = (short*)malloc(len/2);      // allocate buffer for left channel
   right = (short*)malloc(len/2);     // allocate buffer for right channel

   for ( int i=0 ; i < len/4 ; i++ )
   {
      left[i]  = stereo[i*2];
      right[i] = stereo[i*2+1];
   }

   BASS_ChannelGetData(leftencoder, left, len/2); // feed left channel to encoder
   BASS_ChannelGetData(rightencoder,right,len/2); // feed right channel to encoder

   free(left);
   free(right);

   return TRUE;
}


HRESULT InitBASS()
{
   // check the correct BASS was loaded
   if ( HIWORD(BASS_GetVersion()) != BASSVERSION )
   {
      MessageBox(0,"An incorrect version of BASS.DLL was loaded",0,MB_ICONERROR);
      return E_FAIL;
   }

   // initialize BASS recording (default device)
   if ( !BASS_RecordInit(-1) )
   {
      MessageBox(0,"Can't initialize device",0,MB_ICONERROR);
      return E_FAIL;
   }

   // start recording (44100hz, stereo, 16-bit)
   if ( !( channelRec = BASS_RecordStart(44100,2,0,(RECORDPROC*)&RecordProc,0) ) )
   {
      MessageBox(0,"Can't start recording",0,MB_ICONERROR);
      return E_FAIL;
   }

   // Start encoding
   BASS_CHANNELINFO i;
   BASS_ChannelGetInfo(channelRec,&i);

   channel_L  = BASS_StreamCreate( i.freq,1, i.flags|BASS_STREAM_DECODE, NULL, 0 );
   channel_R  = BASS_StreamCreate( i.freq,1, i.flags|BASS_STREAM_DECODE, NULL, 0 );

   BASS_Encode_Start(channel_L, "lame --alt-preset standard - outputL.mp3", BASS_ENCODE_AUTOFREE, NULL, 0);
   BASS_Encode_Start(channel_R, "lame --alt-preset standard - outputR.mp3", BASS_ENCODE_AUTOFREE, NULL, 0);
  
   return S_OK;
}


VOID StopRecording()
{
   BASS_ChannelStop(channelRec);

   BASS_StreamCreateFile(FALSE,"outputL.mp3",0,0,0);
   BASS_StreamCreateFile(FALSE,"outputR.mp3",0,0,0);

   BASS_StreamFree(channel_L);
   BASS_StreamFree(channel_R);
}

Thanks again.

Ian @ un4seen

  • Administrator
  • Posts: 20437
I did the changes you suggested, but the code doesn't still work (the mp3 files are not generated).  :( It perfectly works with WAV (no encoders) and with WMA.

In that case, are you sure you have LAME.EXE in the same directory as your EXE? :)

Check that the BASS_Encode_Start calls are succeeding.

Code: [Select]
VOID StopRecording()
{
   BASS_ChannelStop(channelRec);

   BASS_StreamCreateFile(FALSE,"outputL.mp3",0,0,0);
   BASS_StreamCreateFile(FALSE,"outputR.mp3",0,0,0);

   BASS_StreamFree(channel_L);
   BASS_StreamFree(channel_R);
}

I'd suggest freeing the dummy streams (and so closing the encoders due to the AUTOFREE flag), before trying to open the encoders' output files.

3delite

  • Posts: 907
Need to do the same, and my calculations show that the cycle definition is incorrect.
You have to do it LENGTH / 4 -1 times.

Somebody can confirm this?

EDIT: Or possibly this is only true for Delphi, becouse of the <. I see...

I want to record to two separate mp3 files but I doesn't understand the code above.
I separate the buffer in two buffers. That's done. But then how can I send this two buffers to two encoders?
Push stream?
Please help!

Regards
3delite
« Last Edit: 16 Dec '08 - 18:55 by 3delite »

3delite

  • Posts: 907
Never mind, I solved it with creating two dummy streams with BASS_StreamCreate() give that to BASS_Encode_Start(), and then using BASS_Encode_Write() to feed the data to the encoder in the RECORDPROC. Seems working perfectly.

Regards
3delite

Ian @ un4seen

  • Administrator
  • Posts: 20437
Yep, you can do that or use BASS_ChannelGetData to feed the data to the dummy streams (and encoders) as in the code above. Either way is fine :)