OpenAL воспроизводит захваченные аудиоданные c ++ - PullRequest
4 голосов
/ 27 марта 2012

Я пытаюсь создать программу голосового чата с использованием OpenAL. Кажется, что с сетью все в порядке, но я приму совет по этому поводу =]

Проблема, с которой я столкнулся в данный момент, заключается в попытке воспроизвести захваченные аудиоданные с микрофона. Я следовал найденному коду здесь , чтобы получить микрофонный вход и передать его на динамики.

Это работает нормально, но я не могу воспроизвести полностью захваченный звук после завершения захвата.

Когда какой-то звук захвачен, я сохраняю его в списке, например ...

for (int i = 0; i < CAP_SIZE; i++)
{
    playbackBuffer.push_back( buffer[i] );
}

и затем после завершения захвата я попытался (и не смог) использовать следующий код для воспроизведения этого аудио

ALuint  playbackSource;
alGenSources(1, &playbackSource);
errorCode = alGetError();

ALuint tempPlayback;
alBufferData(tempPlayback, AL_FORMAT_MONO16, &playbackBuffer.front(), playbackBuffer.size()*sizeof(ALuint), FREQ);

// Attach the playback buffer to the new playback source
alSourcei(playbackSource, AL_BUFFER, tempPlayback);
alSourcePlay(playbackSource);

ALint sState = 0;
do
{
    alGetSourcei(playbackSource, AL_SOURCE_STATE, &sState);
}
while ((sState == AL_PLAYING));

При отладке я вижу, что в PlayBuffer содержится много данных, и в этот момент воспроизводится шум в доли секунды, но он не близок к тому, который был захвачен.

РЕДАКТИРОВАТЬ: я добавил строку

alGenBuffers(1, &tempPlayback);

после создания tempPlayback и перед вызовом alBufferData (...), и теперь он воспроизводится в течение правильного промежутка времени, но все, что я слышу, - это высокий шум на протяжении всего пути.

Ответы [ 3 ]

5 голосов
/ 06 июня 2012

Вот действительно простая программа, которая захватывает звук на 5 секунд, делает паузу, затем захватывает еще 5 секунд звука и, наконец, воспроизводит все это (я использовал его для устранения проблемы с захватом один раз).

Он работал на ноутбуке Mint 13 Linux.Mint похож на Ubuntu 12.04

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h>
#include <AL/al.h> 
#include <AL/alc.h> 
#include <sys/time.h>
#include <ctime> 

int main(void) 
{ 
const ALCchar *   devices; 
const ALCchar *         ptr; 
ALCdevice *       mainDev; 
ALCcontext *      mainContext; 
ALCdevice *       captureDev; 
ALubyte           captureBuffer[1048576]; 
ALubyte           *captureBufPtr; 
ALint             samplesAvailable; 
ALint             samplesCaptured; 
time_t            currentTime; 
time_t            lastTime; 
ALuint            buffer; 
ALuint            source; 
ALint             playState; 
int               i; 

// Print the list of capture devices 
printf("Available playback devices:\n");

devices = alcGetString(NULL, ALC_DEVICE_SPECIFIER); 
ptr = devices; 
//while (ptr[0] != NULL)
while (*ptr)
{ 
   printf("   %s\n", ptr); 
   ptr += strlen(ptr) + 1; 
} 

// Open a playback device and create a context first 
printf("Opening playback device:\n"); 
mainDev = alcOpenDevice(NULL); 
if (mainDev == NULL) 
{ 
  printf("Unable to open playback device!\n"); 
  exit(1); 
} 
devices = alcGetString(mainDev, ALC_DEVICE_SPECIFIER); 
printf("   opened device '%s'\n", devices); 
mainContext = alcCreateContext(mainDev, NULL); 
if (mainContext == NULL) 
{ 
  printf("Unable to create playback context!\n"); 
  exit(1); 
} 
printf("   created playback context\n"); 

// Make the playback context current 
alcMakeContextCurrent(mainContext); 
alcProcessContext(mainContext); 

// Print the list of capture devices 

printf("Available capture devices:\n"); 
devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); 
ptr = devices; 

//while (ptr[0] != NULL)
while (*ptr)
{ 
   printf("   %s\n", ptr); 
   ptr += strlen(ptr) + 1; 
}

// Open the default device 
printf("Opening capture device:\n"); 
captureDev = alcCaptureOpenDevice(NULL, 8000, AL_FORMAT_MONO16, 800); 
if (captureDev == NULL) 
{  
  printf("   Unable to open device!\n"); 
  exit(1); 
} 
devices = alcGetString(captureDev, ALC_CAPTURE_DEVICE_SPECIFIER); 
printf("   opened device %s\n", devices); 

// Wait for three seconds to prompt the user 
for (i = 3; i > 0; i--) 
{ 
  printf("Starting capture in %d...\r", i); 
  fflush(stdout); 
  lastTime = time(NULL); 
  currentTime = lastTime; 
  while (currentTime == lastTime) 
  { 
     currentTime = time(NULL); 
     usleep(100000); 
  } 
} 

printf("Starting capture NOW!\n"); 
fflush(stdout); 
lastTime = currentTime; 

// Capture (roughly) five seconds of audio 
alcCaptureStart(captureDev); 
samplesCaptured = 0; 
captureBufPtr = captureBuffer; 
while (currentTime < (lastTime + 5)) 
{ 
  // Get the number of samples available 
  alcGetIntegerv(captureDev, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable); 

  // Copy the samples to our capture buffer 
  if (samplesAvailable > 0) 
  { 
     alcCaptureSamples(captureDev, captureBufPtr, samplesAvailable); 
     samplesCaptured += samplesAvailable; 
     printf("Captured %d samples (adding %d)\r", samplesCaptured, 
        samplesAvailable); 
     fflush(stdout); 

     // Advance the buffer (two bytes per sample * number of samples) 
     captureBufPtr += samplesAvailable * 2; 
  } 

  // Wait for a bit 
  usleep(10000); 

  // Update the clock 
  currentTime = time(NULL); 
} 
printf("\nPausing capture.\n"); 
alcCaptureStop(captureDev); 

// Wait for three seconds to prompt the user 
for (i = 3; i > 0; i--) 
{ 
  printf("Resuming capture in %d...\r", i); 
  fflush(stdout); 
  lastTime = time(NULL); 
  currentTime = lastTime; 
  while (currentTime == lastTime) 
  { 
     currentTime = time(NULL); 
     usleep(100000); 
  } 
} 

printf("Resuming capture NOW!\n"); 
fflush(stdout); 
lastTime = currentTime; 

// Capture (roughly) five seconds of audio 
alcCaptureStart(captureDev); 
while (currentTime < (lastTime + 5)) 
{ 
  // Get the number of samples available 
  alcGetIntegerv(captureDev, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable); 

  // Copy the samples to our capture buffer 
  if (samplesAvailable > 0) 
  { 
     alcCaptureSamples(captureDev, captureBufPtr, samplesAvailable); 
     samplesCaptured += samplesAvailable; 
     printf("Captured %d samples (adding %d)\r", samplesCaptured, 
        samplesAvailable); 
     fflush(stdout); 

     // Advance the buffer (two bytes per sample * number of samples) 
     captureBufPtr += samplesAvailable * 2; 
  } 

  // Wait for a bit 
  usleep(10000); 

  // Update the clock 
  currentTime = time(NULL); 
} 

printf("\nDone capturing.\n"); 
alcCaptureStop(captureDev); 

// Play back the captured data 
printf("Starting playback...\n"); 
fflush(stdout); 

// Generate an OpenAL buffer for the captured data 
alGenBuffers(1, &buffer); 
alGenSources(1, &source); 
alBufferData(buffer, AL_FORMAT_MONO16, captureBuffer,samplesCaptured*2, 8000); 
alSourcei(source, AL_BUFFER, buffer); 
alSourcePlay(source); 

// Wait for the source to stop playing 
playState = AL_PLAYING; 
while (playState == AL_PLAYING) 
{ 
  printf("  source %d is playing...\r", source); 
  fflush(stdout); 
  alGetSourcei(source, AL_SOURCE_STATE, &playState); 
  usleep(100000); 
} 
printf("\nDone with playback.\n"); 
fflush(stdout); 

// Shut down OpenAL 
alDeleteSources(1, &source); 
alDeleteBuffers(1, &buffer); 
alcMakeContextCurrent(NULL); 
alcCloseDevice(mainDev); 
alcCaptureCloseDevice(captureDev); 
}

Скомпилировать с этим:

g++ p.cpp -lalut -lopenal -o p
0 голосов
/ 02 апреля 2012

Единственные программы, которые записывают с микрофона, которые я смог найти в Интернете, - это та, с которой вы начали, и та, которую я отправил вам.Я как бы иду в том же направлении, что и вы.Я отправил вам код, который я пытаюсь изменить.И я иду из стека overoverflow.Я нашел нужный нам код на языке программирования BASIC, но я не очень хорош в этом языке.ссылка:

 http://www.blitzbasic.com/Community/posts.php?topic=90830

If you can get it to work that would be great. And even better, if it
could be change over to c/c++.

I have been looking for microphone capture programs for around two
years. Waiting for some thing simple to come along.
So now I am focusing on the these programs to figure how they work
with debugger and test subroutines figure out the dynamics of freealut.
because I do not see any thing simple comming along any time soon.
OpenAL is the only software I cold get to work.  the documentation
provided by Creative web site is good referance for some one who is
already an expert with the software.
I could not get FBOD, alas, SDL,  Allegro4, or OSS to work because
of a lack of working examples, or no good information.

Good luck.

   keghn
0 голосов
/ 02 апреля 2012
// Compile as: g++ p.cpp -lalut -lopenal -o p
//runs on ubuntu linux for around 2 seconds
#include <AL/al.h>    // OpenAL header files
#include <AL/alc.h>

//#include "stdafx.h"
#include <iostream>
#include <stdio.h>
//#include <windows.h>
//#include <al.h>
//#include <alc.h>


using namespace std;
int main()
{




ALCdevice *dev[2];
ALCcontext *ctx;
ALuint source, buffers[3];
char data[5000];
ALuint buf;
ALint val;

    float ttotal;
    unsigned int ccount;
    long int c1ount;
    c1ount =0;

dev[0] = alcOpenDevice(NULL);
ctx = alcCreateContext(dev[0], NULL);
alcMakeContextCurrent(ctx);

alGenSources(1, &source);
alGenBuffers(3, buffers);

/* Setup some initial silent data to play out of the source */
alBufferData(buffers[0], AL_FORMAT_MONO16, data, sizeof(data), 22050);
alBufferData(buffers[1], AL_FORMAT_MONO16, data, sizeof(data), 22050);
alBufferData(buffers[2], AL_FORMAT_MONO16, data, sizeof(data), 22050);
alSourceQueueBuffers(source, 3, buffers);

/* If you don't need 3D spatialization, this should help processing time */
alDistanceModel(AL_NONE); 

dev[1] = alcCaptureOpenDevice(NULL, 22050, AL_FORMAT_MONO16, sizeof(data)/2); //22050 mean 22.050 samples per     second. or 44100 for 44.1 per second.

/* Start playback and capture, and enter the audio loop */
alSourcePlay(source);
alcCaptureStart(dev[1]);    //starts ring buffer

while(1) 
{
    /* Check if any queued buffers are finished */
    alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
    if(val <= 0)
        continue;

    /* Check how much audio data has been captured (note that 'val' is the
    * number of frames, not bytes) */
    alcGetIntegerv(dev[1], ALC_CAPTURE_SAMPLES, 1, &val);

    /* Read the captured audio */
    alcCaptureSamples(dev[1], data, val);


        //***** Process/filter captured data here *****//


c1ount = c1ount +1;
if(c1ount >= 33){
          break;
         }


        //for (int ii=0;ii<val;++ii) {
        //  data[ii]*=0.1; // Make it quieter
        //}
    //***** end Process/filter captured data here *****//

    /* Pop the oldest finished buffer, fill it with the new capture data,
    then re-queue it to play on the source */
    alSourceUnqueueBuffers(source, 1, &buf);
    alBufferData(buf, AL_FORMAT_MONO16, data, val*2 /* bytes here, not
    frames */, 22050);
    alSourceQueueBuffers(source, 1, &buf);

    /* Make sure the source is still playing */
    alGetSourcei(source, AL_SOURCE_STATE, &val);

    if(val != AL_PLAYING)
    {

        alSourcePlay(source);
    }
}

cout<< "fgggggggg\n";


/* Shutdown and cleanup */
alcCaptureStop(dev[1]);
alcCaptureCloseDevice(dev[1]);

alSourceStop(source);
alDeleteSources(1, &source);
alDeleteBuffers(3, buffers);
alDeleteBuffers(1, &buf);

alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(dev[0]); 

return 0;

}

...