[Openal] Recording and Playing Simultaneously

Daniel PEACOCK dpeacock at creativelabs.com
Mon Jul 23 15:20:00 PDT 2007





Hi,

While alcGetIntergerv ALC_CAPTURE_SAMPLES and alcCaptureSamples use "number
of samples", alBufferData uses bytes not samples.   This works out to be OK
if you are using 8bit Mono - but if you change formats you will need to
change the alBufferData line of code to convert samples to bytes.

In your code below it doesn't show how the Buffer is being attached
(queued) onto the Source.   As you find samples available you need to copy
them to a buffer and then queue the buffer on the end of a playing Source.
The Buffer you are using cannot already be queued on the Source because you
won't be able to change the data (using alBufferData).   So you basically
need to wait until a buffer has processed on the playback Source, then fill
it with captured audio data, and then re-queue it on the end of the Source.

Here is some code that does that.  It assumes an OpenAL playback device has
already been created and initialized.   It also waits for 2 Buffers to be
filled with Captured audio before starting the playback Source.

ALvoid CapturePlayTest(ALvoid)
{
      ALCdevice         *pCaptureDevice;
      const             ALCchar *szDefaultCaptureDevice;
      ALint             lSamplesAvailable;
      ALchar                  ch;
      ALchar                  Buffer[QUEUEBUFFERSIZE];
      ALuint                  SourceID, TempBufferID;
      ALuint                  BufferID[QUEUEBUFFERCOUNT];
      ALuint                  ulBuffersAvailable = QUEUEBUFFERCOUNT;
      ALuint                  ulUnqueueCount, ulQueueCount;
      ALint             lLoop, lFormat, lFrequency, lBlockAlignment,
lProcessed, lPlaying;
      ALboolean         bPlaying = AL_FALSE;
      ALboolean         bPlay = AL_FALSE;
      ALint             lEnv, lDirect, lRoom;

      // NOTE : This code does NOT setup the Wave Device's Audio Mixer to
select a recording input
      // or recording level.

      // Generate a Source and QUEUEBUFFERCOUNT Buffers for Queuing
      alGetError();
      alGenSources(1, &SourceID);

      for (lLoop = 0; lLoop < QUEUEBUFFERCOUNT; lLoop++)
            alGenBuffers(1, &BufferID[lLoop]);

      if (alGetError() != AL_NO_ERROR)
      {
            printf("Failed to generate Source and / or Buffers\n");
            return;
      }

      ulUnqueueCount = 0;
      ulQueueCount = 0;

      // Get list of available Capture Devices
      const ALchar *pDeviceList = alcGetString(NULL,
ALC_CAPTURE_DEVICE_SPECIFIER);
      if (pDeviceList)
      {
            printf("Available Capture Devices are:-\n");

            while (*pDeviceList)
            {
                  printf("%s\n", pDeviceList);
                  pDeviceList += strlen(pDeviceList) + 1;
            }
      }

      szDefaultCaptureDevice = alcGetString(NULL,
ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
      printf("\nDefault Capture Device is '%s'\n\n",
szDefaultCaptureDevice);

      // The next call can fail if the WaveDevice does not support the
requested format, so the application
      // should be prepared to try different formats in case of failure

      lFormat = AL_FORMAT_MONO16;
      lFrequency = 44100;
      lBlockAlignment = 2;

      long lTotalProcessed = 0;
      long lOldSamplesAvailable = 0;
      long lOldTotalProcessed = 0;

      pCaptureDevice = alcCaptureOpenDevice(szDefaultCaptureDevice,
lFrequency, lFormat, lFrequency);
      if (pCaptureDevice)
      {
            printf("Opened '%s' Capture Device\n\n",
alcGetString(pCaptureDevice, ALC_CAPTURE_DEVICE_SPECIFIER));

            printf("Press 1 to Start Recording and Playing\n");
            printf("Press 2 to Stop Recording\n");
            printf("Press Q to quit\n");

            while (1)
            {
                  if (_kbhit())
                  {
                        ch = _getch();
                        ch = toupper( ch );

                        switch(ch)
                        {
                        case '1':
                              alcCaptureStart(pCaptureDevice);
                              bPlay = AL_TRUE;
                              break;

                        case '2':
                              alcCaptureStop(pCaptureDevice);
                              break;
                        }

                        if (ch == 'Q')
                        {
                              alcCaptureStop(pCaptureDevice);
                              break;
                        }
                  }
                  else
                  {
                        alGetError();

                        alcGetIntegerv(pCaptureDevice, ALC_CAPTURE_SAMPLES,
1, &lSamplesAvailable);

                        if ((lOldSamplesAvailable != lSamplesAvailable) ||
(lOldTotalProcessed != lTotalProcessed))
                        {
                              printf("Samples available is %d, Buffers
Processed %d    \n", lSamplesAvailable, lTotalProcessed);
                              lOldSamplesAvailable = lSamplesAvailable;
                              lOldTotalProcessed = lTotalProcessed;
                        }

                        // If the Source is (or should be) playing, get
number of buffers processed
                        // and check play status
                        if (bPlaying)
                        {
                              alGetSourcei(SourceID, AL_BUFFERS_PROCESSED,
&lProcessed);
                              while (lProcessed)
                              {
                                    lTotalProcessed++;

                                    // Unqueue the buffer
                                    alSourceUnqueueBuffers(SourceID, 1,
&TempBufferID);

                                    // Update unqueue count
                                    if (++ulUnqueueCount ==
QUEUEBUFFERCOUNT)
                                          ulUnqueueCount = 0;

                                    // Increment buffers available
                                    ulBuffersAvailable++;

                                    lProcessed--;
                              }

                              // If the Source has stopped (been starved of
data) it will need to be
                              // restarted
                              alGetSourcei(SourceID, AL_SOURCE_STATE,
&lPlaying);
                              if (lPlaying == AL_STOPPED)
                              {
                                    printf("Buffer Stopped, Buffers
Available is %d                             \n", ulBuffersAvailable);
                                    bPlay = AL_TRUE;
                              }
                        }

                        if ((lSamplesAvailable > (QUEUEBUFFERSIZE /
lBlockAlignment)) && !(ulBuffersAvailable))
                        {
                              OutputDebugString("underrun!\n");
                        }
                        else
                        // When we have enough data to fill our
QUEUEBUFFERSIZE byte buffer, grab the samples
                        if ((lSamplesAvailable > (QUEUEBUFFERSIZE /
lBlockAlignment)) && (ulBuffersAvailable))
                        {
                              // Consume Samples
                              alcCaptureSamples(pCaptureDevice, Buffer,
QUEUEBUFFERSIZE / lBlockAlignment);

                              alBufferData(BufferID[ulQueueCount], lFormat,
Buffer, QUEUEBUFFERSIZE, lFrequency);

                              // Queue the buffer, and mark buffer as
queued
                              alSourceQueueBuffers(SourceID, 1,
&BufferID[ulQueueCount]);

                              if (++ulQueueCount == QUEUEBUFFERCOUNT)
                                    ulQueueCount = 0;

                              // Decrement buffers available
                              ulBuffersAvailable--;

                              // If we need to start the Source do it now
IF AND ONLY IF we have queued at least 2 buffers
                              if ((bPlay) && (ulBuffersAvailable <=
(QUEUEBUFFERCOUNT - 2)))
                              {
                                    alSourcePlay(SourceID);
                                    printf("Buffer Starting
\n");
                                    bPlaying = AL_TRUE;
                                    bPlay = AL_FALSE;
                              }
                        }
                  }
            }

            alcCaptureCloseDevice(pCaptureDevice);
      }
      else
      {
            printf("WaveDevice is unavailable, or does not supported the
request format\n");
      }

      alSourceStop(SourceID);
      alDeleteSources(1, &SourceID);
      for (lLoop = 0; lLoop < QUEUEBUFFERCOUNT; lLoop++)
            alDeleteBuffers(1, &BufferID[lLoop]);
}

Dan
Creative Labs, Inc.

Notice
The information in this message is confidential and may be legally
privileged.  It is intended solely for the addressee.  Access to this
message by anyone else is unauthorized.  If you are not the intended
recipient,  any disclosure,  copying or distribution of the message,  or
any action taken by you in reliance on it,  is prohibited and may be
unlawful.  If you have received this message in error,  please delete it
and contact the sender immediately.  Thank you.




                                                                           
             Spike7d5                                                      
             <spike7d5 at yahoo.c                                             
             om>                                                        To 
             Sent by:                  openal at opensource.creative.com      
             openal-bounces at op                                          cc 
             ensource.creative                                             
             .com                                                  Subject 
                                       [Openal] Recording and Playing      
                                       Simultaneously                      
             07/23/2007 02:17                                              
             PM                                                            
                                                                           
                                                                           
                                                                           
                                                                           





Hello,

I want to record and play sound at the same time, but I don't know how to
do
this. I've managed to play my own recordings, but I can't manage to combine
these 2 together. Can anybody help me, please?

Throughout the program, every AL function is checked for errors, and one
appears at alBufferData - "invalid value passed to AL function". Here is a
small portion of my code, that I believe is important. And also, I must say
that the program never gets to that printf.



ALCdevice *deviceCapture = alcCaptureOpenDevice(NULL, 22050,
AL_FORMAT_MONO8, (ALCsizei) 10000);
...
char bufferCapture[220500];
int total = 0;
while (key != 27)
{
             ALCint samples;
             alcGetIntegerv(deviceCapture, ALC_CAPTURE_SAMPLES, 1,
&samples);

             if (samples >= 1)
             {
                         alcCaptureSamples(deviceCapture, bufferCapture,
samples);
                         if ((result = alGetError()) == AL_NO_ERROR)
                         {
                                     alBufferData(buffer, AL_FORMAT_MONO8,
bufferCapture, samples, 22050);
                                     if ((result = alGetError()) !=
AL_NO_ERROR)
                                     {
                                                 printf("Error setting
capture buffer: %s\n", getErrorString(result));
                                                 _getch();
                                                 return -1;
                                     }

                                     alSourcePlay(source);

                                     total += samples;
                                     printf("%d\n", total);
                         }
                         else
                         {
                                     printf("Error getting samples: %s\n",
getErrorString(result));
                                     _getch();
                                     return -1;
                         }
             }

             if (_kbhit())
                         key = _getch();
}
--
View this message in context:
http://www.nabble.com/Recording-and-Playing-Simultaneously-tf4132517.html#a11752973

Sent from the OpenAL - User mailing list archive at Nabble.com.

_______________________________________________
Openal mailing list
Openal at opensource.creative.com
http://opensource.creative.com/mailman/listinfo/openal

ForwardSourceID:NT00044582



More information about the Openal mailing list