Пытаюсь Воспроизвести звук при помощи связки OpenAL+FFmpeg Вывода звука вроде добился, но звук идет с прерываниями ,треском(Треск особенно заметен если уменьшать размер буффера) и как-будто заикаится что-ли. Вот так я декодирую и передаю звук в OpenAL
function TOggStream.Playback: Boolean; begin if Playing then begin Result := True; exit; end; if not Stream(Buffers[0]) then begin Result := False; exit; end; if not Stream(Buffers[1]) then begin Result := False; exit; end; alSourceQueueBuffers(Source, 2, @Buffers); alSourcePlay(Source); Result := True; end; function TOggStream.Update: Boolean; var Processed: Integer; Active: Boolean; Buffer: TALUInt; begin Active := False; alGetSourcei(Source, AL_BUFFERS_PROCESSED, @Processed); if Processed > 0 then repeat alSourceUnqueueBuffers(source, 1, @Buffer); Active := Stream(Buffer); alSourceQueueBuffers(source, 1, @Buffer); dec(Processed); until Processed <= 0; Result := Active; end; function TOggStream.Stream(Buffer : TALUInt) : Boolean; var MMyData,MMyData2: PByte; dataa:byte; Size,NewSize : Integer; Res,Mres : Integer; ff,icnt,remaining,decoded: integer; BufferTMP:array[1..BufferSize] of Integer; begin Size := 0; zeroMemory(@BufferTMP,SizeOf(BufferTMP)); while (Size < BufferSize) do begin av_read_frame(fmt_ctx, @MyPacket); begin if(MyPacket.stream_index=audio_index) then begin decoded:=avcodec_decode_audio4(dec_ctxAud, AudFrame, ff, @MyPacket); if ff>0 then begin Res:=av_samples_get_buffer_size(@AudFrame.linesize[0], AudFrame.channels,Audframe.nb_samples, dec_ctxAud.sample_fmt,1);; av_samples_alloc(MmyData, @AudFrame.linesize[0], AudFrame.channels, AudFrame.nb_samples, AV_SAMPLE_FMT_S16, 0); FrameFinished := swr_convert(swr,MmyData, AudFrame.nb_samples,AudFrame.Data[0] , AudFrame.nb_samples); Mres:=av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)*AudFrame.channels*FrameFinished; CopyMemory(@BufferTMP, MmyData, Mres ); end; Application.ProcessMessages; end; av_free_packet(@MyPacket); end; if Res > 0 then begin inc(Size,Res); end else if Res < 0 then Log.Add(ErrorString(Res)) else break; end; alBufferData(Buffer, audFormat, @BufferTMP, size,dec_ctxAud.sample_rate ); Result := True; end;
Если будет нужно приложу весь исходный код, кто сталкивался, подскажите пожалуйста
С этим делом я ещё не разбирался, но в исходниках Newton Dynamics в OpenAL накопал как раз код декодирования звука FFmpeg, и он гораздо больше твоего :) сам потом хочу его использовать.
RedCat
а если Application.ProcessMessages; закомментировать ?
просто тут как - ты в своем цикле говоришь внешнему гуи обновиться(проверить состояния...) тут появляются временные задержки и они могут быть разными по длительности,
отсюда происходят провалы в воспроизведении и соответственно заикания.
Могу только посоветовать использовать отдельный поток - в котором у тебя будет производится все что связано со звуком.
Daniil Petrov
С этим делом я ещё не разбирался, но в исходниках Newton Dynamics в OpenAL накопал как раз код декодирования звука FFmpeg, и он гораздо больше твоего :) сам потом хочу его использовать.
Этот код, некая модификация известного примера OGG_OpenAl где используется библиотека vorbis, спасибо за ссылку посмотрю
gambit_oz
RedCat
а если Application.ProcessMessages; закомментировать ?
просто тут как - ты в своем цикле говоришь внешнему гуи обновиться(проверить состояния...) тут появляются временные задержки и они могут быть разными по длительности,
отсюда происходят провалы в воспроизведении и соответственно заикания.
Могу только посоветовать использовать отдельный поток - в котором у тебя будет производится все что связано со звуком.
Спасибо ограмное за совет я обязательно попробую.
А еще у меня было предположение что вся проблема в том что массив BufferTMP в конце забит 0 или OpenAl игнорирует 0 в конце буффера?
gambit_oz
RedCat
а если Application.ProcessMessages; закомментировать ?
просто тут как - ты в своем цикле говоришь внешнему гуи обновиться(проверить состояния...) тут появляются временные задержки и они могут быть разными по длительности,
отсюда происходят провалы в воспроизведении и соответственно заикания.
Могу только посоветовать использовать отдельный поток - в котором у тебя будет производится все что связано со звуком.
К сожалению удаление из кода processsmessage не помогло, и вынос в отдельный поток тоже
заикание результат либо окончания буфера прежде чем был добавлен следующий, либо неверного чтения блоков.
Требуется накачать десяток буферов перед запуском проигрывания, кроме того частота вызова функции докачки блоков неопределена, и точно зафиксировать не получиться, проще поддерживать определенный запас, и бросать несколько блоков за раз, если понадобиться.
как следствие
-запуск декодера в отдельном потоке с подъемом приоритета потока до максимального.
-декодер непрерывно работает пока не создаст запас блоков на половину секунды, или около того(не 2 блока большого размера а 100 мелкого)
-поток ожидает в таймере половину накопленного периода времени, и потом повторяет цикл вновь.
-воспроизведение начинается не раньше чем буфер будет заполнен блоками полностью в первый раз
при достижении нормального звука можно поэкспериментировать с урезанием длины запаса и увеличением частоты обновления буфера, но момент начала заиканий зависит от нагрузки процессора в данный момент. Предположение о том что функция ожидающая 1ms подождет 1ms излишне оптимистичны. поэтому затруднительно поддерживать частоту заливки буферов близкую их длине.
ShadowTeolog
> -запуск декодера в отдельном потоке с подъемом приоритета потока до максимального.
А сейчас так и делают, запускают декодирование звука и изображения в двух отдельных от основного потоках, я так и собираюсь делать!
ShadowTeolog
заикание результат либо окончания буфера прежде чем был добавлен следующий, либо неверного чтения блоков.
Требуется накачать десяток буферов перед запуском проигрывания, кроме того частота вызова функции докачки блоков неопределена, и точно зафиксировать не получиться, проще поддерживать определенный запас, и бросать несколько блоков за раз, если понадобиться.
как следствие
-запуск декодера в отдельном потоке с подъемом приоритета потока до максимального.
-декодер непрерывно работает пока не создаст запас блоков на половину секунды, или около того(не 2 блока большого размера а 100 мелкого)
-поток ожидает в таймере половину накопленного периода времени, и потом повторяет цикл вновь.
-воспроизведение начинается не раньше чем буфер будет заполнен блоками полностью в первый раз
при достижении нормального звука можно поэкспериментировать с урезанием длины запаса и увеличением частоты обновления буфера, но момент начала заиканий зависит от нагрузки процессора в данный момент. Предположение о том что функция ожидающая 1ms подождет 1ms излишне оптимистичны. поэтому затруднительно поддерживать частоту заливки буферов близкую их длине.
Спасибо, Ваш совет помог! все работает как нужно, за исключением одного, проц загружен в пределах 40-70% так же по идее быть не должно?
Все разобрался, в потоке декодирования написал Sleep(1); нагрузка на ЦП стала не более 3%
Раз тема разрешилась, спрошу своё, никто не пробовал libflac в играх? Как оно по скорости?
Dimich
> Раз тема разрешилась, спрошу своё, никто не пробовал libflac в играх? Как оно по скорости?
А чем хуже Ogg Vorbis?
Daniil Petrov
> А чем хуже Ogg Vorbis?
Кто сказал, что хуже?
Dimich
А зачем тогда тебе flac :)
Daniil Petrov
> А зачем тогда тебе flac :)
чтоб игра внушительно весила, чтоб её качали, думая что это ааа тайтл
RedCat
сделал то что?
*Lain*
> чтоб игра внушительно весила, чтоб её качали, думая что это ааа тайтл
Наподобие этой хохмы? Как палка копчёной колбасы в штанах для понта :)))
Тема в архиве.