OpenAL 流式播放音频的时候结尾有杂音。

57 views
Skip to first unread message

Xpol Wan

unread,
Jul 1, 2013, 9:48:28 PM7/1/13
to gamed...@googlegroups.com
大家好,

在OpenAL list里面问没有人搭理,只好来这里求助。

我在做一个简单的游戏引擎,音频部分的PC实现采用的是OpenAL。

但是我发现流式播放音频的时候,结尾会有杂音。具体的说就是播放完毕后
还会播放该音频的某段声音,持续很短。就像是alSourceStop没有真正刹住车
一样。

我的环境是Windows7。有和其他游戏引擎Love2D比较过。Love2D却没有这个现象。
我开始猜想是不是我用的是单线程的原因。经过改成一个解码一个播放线程后情况依旧。

我也有试过OpenAL 1.1 SDK [1] 里面带的sample中的playstream例子(见后面的代码)。
情况是一样的,结尾还是有杂音。

由于刚刚开始接触较底层的音频编程也是刚刚开始使用OpenAL,所以请各位有经验的帮忙指点一下。


[1] OpenAL 1.1 SDK: http://connect.creativelabs.com/openal/Downloads/OpenAL11CoreSDK.zip

SDK中的 PlayStream.cpp:


#include "Framework.h"
#include "CWaves.h"

#define NUMBUFFERS              (4)
#define SERVICE_UPDATE_PERIOD (20)

#define TEST_WAVE_FILE "stereo.wav"

int main()
{
ALuint     uiBuffers[NUMBUFFERS];
ALuint     uiSource;
ALuint uiBuffer;
ALint iState;
CWaves * pWaveLoader = NULL;
WAVEID WaveID;
ALint iLoop;
ALint iBuffersProcessed, iTotalBuffersProcessed, iQueuedBuffers;
WAVEFORMATEX wfex;
unsigned long ulDataSize = 0;
unsigned long ulFrequency = 0;
unsigned long ulFormat = 0;
unsigned long ulBufferSize;
unsigned long ulBytesWritten;
void * pData = NULL;

// Initialize Framework
ALFWInit();

ALFWprintf("PlayStream Test Application\n");

if (!ALFWInitOpenAL())
{
ALFWprintf("Failed to initialize OpenAL\n");
ALFWShutdown();
return 0;
}

    // Generate some AL Buffers for streaming
alGenBuffers( NUMBUFFERS, uiBuffers );

// Generate a Source to playback the Buffers
    alGenSources( 1, &uiSource );

// Create instance of WaveLoader class
pWaveLoader = new CWaves();
if ((pWaveLoader) && (SUCCEEDED(pWaveLoader->OpenWaveFile(ALFWaddMediaPath(TEST_WAVE_FILE), &WaveID))))
{
pWaveLoader->GetWaveSize(WaveID, &ulDataSize);
pWaveLoader->GetWaveFrequency(WaveID, &ulFrequency);
pWaveLoader->GetWaveALBufferFormat(WaveID, &alGetEnumValue, &ulFormat);

// Queue 250ms of audio data
pWaveLoader->GetWaveFormatExHeader(WaveID, &wfex);
ulBufferSize = wfex.nAvgBytesPerSec >> 2;

// IMPORTANT : The Buffer Size must be an exact multiple of the BlockAlignment ...
ulBufferSize -= (ulBufferSize % wfex.nBlockAlign);

if (ulFormat != 0)
{
pData = malloc(ulBufferSize);
if (pData)
{
// Set read position to start of audio data
pWaveLoader->SetWaveDataOffset(WaveID, 0);

// Fill all the Buffers with audio data from the wavefile
for (iLoop = 0; iLoop < 4; iLoop++)
{
if (SUCCEEDED(pWaveLoader->ReadWaveData(WaveID, pData, ulBufferSize, &ulBytesWritten)))
{
alBufferData(uiBuffers[iLoop], ulFormat, pData, ulBytesWritten, ulFrequency);
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
}
}

// Start playing source
alSourcePlay(uiSource);

iTotalBuffersProcessed = 0;

while (!ALFWKeyPress())
{
Sleep( SERVICE_UPDATE_PERIOD );

// Request the number of OpenAL Buffers have been processed (played) on the Source
iBuffersProcessed = 0;
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);

// Keep a running count of number of buffers processed (for logging purposes only)
iTotalBuffersProcessed += iBuffersProcessed;
ALFWprintf("Buffers Processed %d\r", iTotalBuffersProcessed);

// For each processed buffer, remove it from the Source Queue, read next chunk of audio
// data from disk, fill buffer with new data, and add it to the Source Queue
while (iBuffersProcessed)
{
// Remove the Buffer from the Queue.  (uiBuffer contains the Buffer ID for the unqueued Buffer)
uiBuffer = 0;
alSourceUnqueueBuffers(uiSource, 1, &uiBuffer);

// Read more audio data (if there is any)
pWaveLoader->ReadWaveData(WaveID, pData, ulBufferSize, &ulBytesWritten);
if (ulBytesWritten)
{
// Copy audio data to Buffer
alBufferData(uiBuffer, ulFormat, pData, ulBytesWritten, ulFrequency);
// Queue Buffer on the Source
alSourceQueueBuffers(uiSource, 1, &uiBuffer);
}

iBuffersProcessed--;
}

// Check the status of the Source.  If it is not playing, then playback was completed,
// or the Source was starved of audio data, and needs to be restarted.
alGetSourcei(uiSource, AL_SOURCE_STATE, &iState);
if (iState != AL_PLAYING)
{
// If there are Buffers in the Source Queue then the Source was starved of audio
// data, so needs to be restarted (because there is more audio data to play)
alGetSourcei(uiSource, AL_BUFFERS_QUEUED, &iQueuedBuffers);
if (iQueuedBuffers)
{
alSourcePlay(uiSource);
}
else
{
// Finished playing
break;
}
}
}

// Stop the Source and clear the Queue
alSourceStop(uiSource);
alSourcei(uiSource, AL_BUFFER, 0);

// Release temporary storage
free(pData);
pData = NULL;
}
else
{
ALFWprintf("Out of memory\n");
}
}
else
{
ALFWprintf("Unknown Audio Buffer format\n");
}

// Close Wave Handle
pWaveLoader->DeleteWaveFile(WaveID);
}
else
{
ALFWprintf("Failed to load %s\n", ALFWaddMediaPath(TEST_WAVE_FILE));
}

    // Clean up buffers and sources
alDeleteSources( 1, &uiSource );
alDeleteBuffers( NUMBUFFERS, uiBuffers );

if (pWaveLoader)
delete pWaveLoader;

ALFWShutdownOpenAL();

ALFWShutdown();

    return 0;
}

Reply all
Reply to author
Forward
0 new messages