我需要播放从网络中获取的声音。每10毫秒,一个882字节的声音(单声道,16位,44100赫兹)。这样做:
while (!ExitKey)
{
boost::system::error_code error;
size_t len = VoiceSocket->read_some(boost::asio::buffer(buf), error);
if (len==0)
{
continue;
}
alGenSources(1, &alSource);
alGenBuffers(1, &alSampleSet);
alBufferData(alSource, AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
alSourcei(alSource, AL_BUFFER, alSampleSet);
alSourcePlay(alSource);
}
但我的声音不是播放。在buf变量我有声音,因为如果我发送到文件,我有文件声。
答案 0 :(得分:4)
您的代码未显示alListener
。这似乎有点太明显,因为错误,但没有听众,听不到声音,否则发布的代码应该产生一些声音,假设插座中有非零数据。
编辑:再看一下,你有一个小错字,这会产生很大的影响。 alBufferData(alSource, ...)
应为alBufferData(alSampleSet, ...)
。您想要填充缓冲区对象,而不是源。否则,你正在播放一个空缓冲区,毫不奇怪,它不会产生声音。
另请注意,您的代码通常效率低下,无法按预期工作。
您肯定不希望为每10ms收到的每个数据包生成新的源(和缓冲区)。这会产生一些声音,但不是你想要的声音。即使没有网络抖动(你将不可避免地存在),如果没有可听见的间隙,这将无法很好地发挥作用。
在进入循环之前,生成一个源和至少3个缓冲区(更好一些,5或6个)。只要你正在流媒体,这个来源就会存在,并且它会继续播放。
在进入循环之前至少接收2个缓冲区。按照收到的顺序将这些缓冲区排入源(alSourceQueueBuffers
)并开始播放。无论何时收到新数据包,都要将数据读入新缓冲区(从分配缓冲区的空闲列表中提取)并排队。
将缓冲区排队并在它们变为空闲时将它们重新列入您的空闲列表(首先查询!)。
这样,OpenAL在播放声音时总会有一些数据需要读取,这对于获得好的结果至关重要。永远不要让它饿死。
答案 1 :(得分:0)
因此,如果原始缓冲区中存在有效数据,则需要使用alGetError检查OpenAL函数,以查看其中一些是否失败并找出它们失败的原因。从问题描述中我没有看到这个基本检查已经完成。
答案 2 :(得分:0)
我写这段代码:
void Sound::GoChat()
{
device = alcOpenDevice(NULL);
//
ofstream file;
file.open("TESTSPEAKER", std::ios_base::binary);
context = alcCreateContext(device, NULL);
alcMakeContextCurrent(context);
// alGetError();
char *alBuffer;
ALenum alFormatBuffer;
ALsizei alFreqBuffer;
long alBufferLen;
ALboolean alLoop;
unsigned int alSource;
unsigned int alSampleSet[3];
boost::array <char, 882> buf;
int NumberOfSampleSet = 0;
alGenSources(1, &alSource);
alGenBuffers(3, alSampleSet);
//
alBufferData(alSampleSet[0], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
alBufferData(alSampleSet[1], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
alBufferData(alSampleSet[2], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
alSourceQueueBuffers(alSource, 3, alSampleSet);
//
while (!ExitKey)
{
alSourceUnqueueBuffers(alSource, 3, alSampleSet);
boost::system::error_code error;
size_t len = VoiceSocket->read_some(boost::asio::buffer(buf), error);
if (len==0)
{
continue;
}
file.write(buf.data(), 882);
alBufferData(alSampleSet[0], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
alBufferData(alSampleSet[1], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
alBufferData(alSampleSet[2], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
alSourcei(alSource, AL_BUFFER, alSampleSet[0]);
alSourcei(alSource, AL_BUFFER, alSampleSet[1]);
alSourcei(alSource, AL_BUFFER, alSampleSet[2]);
alSourceQueueBuffers(alSource, 3, alSampleSet);
//
//alSourcei(alSource, AL_LOOPING, alSampleSet);
alSourcePlay(alSource);
alErr = alGetError();
//
}
VoiceSocket->close();
file.close();
}
但这也不行(