Мне нужно воспроизвести звук, который я беру из сети. Каждые 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 у меня есть звук, потому что, если я посылаю это в файл, у меня есть звук в файле.
Ваш код не показывает alListener
, Это кажется слишком очевидным как ошибка, но слушатель не слышит, звук не слышен, и в противном случае опубликованный код должен издавать звук, предполагая, что из сокета поступают ненулевые данные.
РЕДАКТИРОВАТЬ: На второй взгляд, у вас есть небольшая опечатка, которая имеет большое значение. alBufferData(alSource, ...)
должно быть alBufferData(alSampleSet, ...)
, Вы хотите заполнить буферный объект, а не источник. В противном случае вы проигрываете пустой буфер, что неудивительно, что звук не воспроизводится.
Также обратите внимание, что ваш код в целом неэффективен и не будет работать так, как задумано.
Вы определенно не хотите генерировать новый источник (и буфер) для каждого пакета, который вы получаете каждые 10 мс. Это будет производить немного звук, но не то, что вы хотите. Даже без дрожания сети (которое у вас неизбежно будет) это не будет хорошо играть без слышимых пауз.
Создайте один источник и по крайней мере 3 буфера (лучше еще несколько, 5 или 6) перед входом в цикл. Один источник живет до тех пор, пока вы транслируете, и он продолжает играть в течение этого времени.
Получите по крайней мере 2 буфера, прежде чем войти в цикл. Поставить эти буферы в очередь к источнику (alSourceQueueBuffers
) в том порядке, в котором вы их получили, и начинайте играть. Всякий раз, когда вы получаете новый пакет, считывайте данные в новый буфер (извлекайте его из свободного списка выделенных буферов) и ставьте в очередь.
Снимите очередь с буферов и переместите их в свой свободный список, когда они станут свободными (сначала запросите!).
Таким образом, у OpenAL всегда есть данные для чтения во время воспроизведения звука, что крайне важно для получения хорошего результата. Никогда не позволяйте этому голодать.
Поэтому, если в необработанном буфере есть действительные данные, необходимо проверить функции OpenAL с помощью alGetError, чтобы выяснить, не произошли ли некоторые из них, и выяснить, почему они не сработали. Из описания вопроса я не увидел, что эта базовая проверка была сделана.
Я пишу этот код:
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();
}
но это тоже не работает (