使用OpenAL(流)播放声音
Play sound with OpenAL(Stream)
我需要播放从网络上获取的声音。每10ms,一个占用882字节的声音(单声道,16位,44100 Hz)。这样做:
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变量中,我有声音,因为如果我把它发送到文件中,我就在文件中有声音。
您的代码不显示alListener
。这似乎有点太明显了,因为这是一个错误,但没有监听器,也听不到声音,否则发布的代码应该会产生一些声音,假设套接字中有非零数据。
编辑:仔细一看,您有一个小的打字错误,这会产生很大的后果。alBufferData(alSource, ...)
应该是alBufferData(alSampleSet, ...)
。您要填充缓冲区对象,而不是源。否则,你播放的是一个空缓冲区,这不足为奇地不会产生声音。
还要注意,您的代码通常效率低下,无法按预期工作。
您绝对不想为每10ms收到的每个数据包生成一个新的源(和缓冲区)。这会产生一些的声音,但不是你想要的。即使没有网络抖动(这是不可避免的),如果没有可听见的间隙,这也不会很好地播放。
在进入循环之前生成一个源和至少3个缓冲区(最好是多出几个,5个或6个)。只要你在流媒体播放,唯一的来源就会一直存在,而且它会一直播放。
在进入循环之前至少接收2个缓冲区。将这些缓冲区按接收顺序排列到源(alSourceQueueBuffers
),然后开始播放。每当你收到一个新的数据包时,把数据读入一个新缓冲区(从已分配缓冲区的空闲列表中提取)并排队
对缓冲区进行排队,并在它们变为可用时将其重新命名到可用列表中(先查询!)。
这样,OpenAL在播放声音时总是有一些数据要读取,这对获得好的结果至关重要。永远不要让它挨饿。
因此,如果原始缓冲区中有有效数据,则需要使用alGetError检查OpenAL函数,看看其中是否有一些函数失败,并找出它们失败的原因。从问题描述中,我没有看到这个基本检查已经完成。
我写的代码是:
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();
}
但这也不起作用(
- 如何在C++中播放声音?
- 有没有办法毫不拖延地播放声音?
- 在不打开应用程序的情况下在MinGW c++中播放声音(.wav)文件
- 如何在QT中飞溅之前播放声音?
- 计时器达到零时如何播放声音?
- 使用MinGW播放声音
- 如何从McIsendstring()中解决此错误并使其播放声音
- 如何在 c++ 中播放声音
- 视觉 在C++中正确使用播放声音功能
- 切换音频设备时播放声音的SDL问题
- 有没有一种简单的方法可以使用SFML在后台线程中播放声音
- 如何使用7.1音频系统sfml播放声音
- 在做其他事情时,在C 中播放声音
- 当Windows XP(32位,SP3)播放声音时,随机应用程序暂停半秒钟
- 在 DirectX Windows 8 应用中播放声音
- C 确定是否播放声音
- 播放 C/C++ 声音的最简单方法
- 使用OpenAL(流)播放声音
- 使用 OpenAL 播放声音
- OpenAL不播放声音