Russian Qt Forum
Ноябрь 23, 2024, 03:52 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Заикание звука - Qt + RtAudio  (Прочитано 6316 раз)
Jey
Гость
« : Январь 24, 2011, 02:49 »

Добрый день  Улыбающийся
Работаю над программой, которая должна стримить аудио и воспроизводить его.
Включил в свой msvs-qt-проект для этой цели oggz, libfishsound и RtAudio.
Пишу сейчас непосредственно проигрыватель.
Суть проблемы в том, что при воспроизведении звук страшно "заикается".

libfishsound декодирует для меня ogg-файл, предоставляя pcm-данные.
Для проверки корректности этих данных я сливал их в wav-файл с помощью либы libsndfile - в винампе этот файл воспроизводился корректно (однако, с какими-то негромкими пощелкиваниями на басах).
Помимо RtAudio я успел использовать portaudio - получил то же самое. Причем пробовал метод и с callback'ом и с блокирующей записью.
Во всех случаях пробовал играть с различными программными настройками для этих либ.
А до всего этого также пробовал QAudioOutput, но кроме шипения ничего не получил  Улыбающийся

Я собрал минималистичный проект, в котором считываются pcm-данные из файлика. Данные я слил в файлик с помощью основного проекта.
Как результат - при его воспроизведении тоже получилось заикание.
RtAudio в данной конфигурации использует direct sound. PCM-данные имеют тип float interleaved.
Если кто-нибудь подозревает в чем проблема, подскажите, пожалуйста Улыбающийся Я с этим уже довольно долго не разберусь никак.
Может быть, я неправильно использую выходящий от декодера float** в моем проекте?
Я нагло интерпретирую его как void* и скармливаю RtAudio. Ни при каких других испробованных мною вариаций ничего  хорошего не воспроизводилось вообще Улыбающийся


Скомпилированный проект (для прверки) можно скачать тут.
Исходники (msvs10) - здесь.
Файл с обрезком pcm в них приложил.

Код:
#include <QtCore/QCoreApplication>
#include <QFile.h>
#include <QDebug.h>
#include "RtAudio.h"

RtAudio *rtAudio;
RtAudio::StreamParameters streamParams;
RtAudio::StreamOptions streamOptions;
unsigned int sampleRate;
unsigned int bufferSize;

QFile pcmfile; // Файл с pcm-данными


// Функция заполнения буфера данными
int feed(char *buffer, quint32 nFrames)
{
if ( pcmfile.atEnd() )
return 1;

Q_ASSERT (
                       // Непосредственное чтение данных из файла в buffer
pcmfile.read ( buffer, nFrames*sizeof(float) ) != -1 );

return 0;
}

// Callback для RtAudio, просто вызывающий feed с двумя параметрами
int RtCallback(void *outputBuffer, void *inputBuffer, quint32 nFrames,
double streamTime, RtAudioStreamStatus status, void *userData)
{
if ( status )
qDebug() << "Stream overflow detected!";
return feed ( (char*)outputBuffer, nFrames );
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

// Инициализация RtAudio, заполнение параметров стрима
rtAudio  = new RtAudio( RtAudio::WINDOWS_DS );
streamParams.deviceId  = rtAudio -> getDefaultOutputDevice();
streamParams.firstChannel  = 0;
streamParams.nChannels  = 2;
streamOptions.flags             = 0 /*RTAUDIO_MINIMIZE_LATENCY*/;
streamOptions.numberOfBuffers     = 2;
streamOptions.priority  = 0;
streamOptions.streamName  = "default";

sampleRate = 44100;
bufferSize = 4096;     // (пробовал различный размер буфера и их число - все равно заикается)

Q_ASSERT ( rtAudio -> getDeviceCount() > 0 ); // проверка наличия устройства для воспр-я

pcmfile.setFileName ( "pcmdata-truncated" );
Q_ASSERT( pcmfile.open( QIODevice::ReadOnly ));

rtAudio -> openStream( &streamParams, 0, RTAUDIO_FLOAT32,
sampleRate, &bufferSize, RtCallback, 0, &streamOptions );

           // Старт воспроизведения
rtAudio -> startStream();

return a.exec();
}
« Последнее редактирование: Январь 24, 2011, 02:50 от Jey » Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #1 : Январь 24, 2011, 15:51 »

А попробуй так:

Код
C++ (Qt)
unsigned int devId = rtAudio -> getDefaultOutputDevice();
 
RtAudio::DeviceInfo info;
info = rtAudio ->getDeviceInfo(devId );
 
RtAudio::StreamParameters streamParams;
streamParams.deviceId = devId;
streamParams.nChannels = info.outputChannels;
streamParams.firstChannel = 0;
 
RtAudio::StreamOptions streamsOptions;
streamsOptions.flags = RTAUDIO_NONINTERLEAVED;
 
sampleRate = 44100;
bufferSize = 512;
 
rtAudio -> openStream( &streamParams, 0, RTAUDIO_FLOAT32,
sampleRate, &bufferSize, RtCallback, 0, &streamOptions );
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Jey
Гость
« Ответ #2 : Январь 24, 2011, 17:39 »

Спасибо за ответ  Улыбающийся Попробовал с таким сеттингом. Вот что получилось.
Заикания при этом нет  Улыбающийся На этом хорошее кончается и начинается: играет только одна колонка, а звук такой, будто группа орков дает концерт Веселый
(А в дополнение к этому я услышал те же пощелкивания на басах, как тогда, когда я полученные декодированные данные слил в wav-файл с помощью libsndfile и воспроизвел его в винампе).
В этот раз, как я понял, мы указываем RtAudio рассматривать данные как non-interleaved. Но они должны быть все же interleaved, потому что
в декодере я  вызывал функцию fish_sound_set_decoded_float_ilv(). Попробовал вместо этого вызвать fish_sound_set_decoded_float(), чтобы
в дальнейшем получить non-interleaved данные и воспроизвести их в этом же примере - получился просто шум  В замешательстве

Еще при буфере размером 512 постоянно срабатывало qDebug() << "Stream overflow detected!"; Я немного увеличил его, чтобы этого не происходило.
Но на звук это ощутимо не повлияло Улыбающийся
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #3 : Январь 24, 2011, 18:57 »

А если попробовать выввод через ASIO драйвер?

http://www.asio4all.com/
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Akon
Гость
« Ответ #4 : Январь 25, 2011, 22:40 »

У меня QAudioOutput/QAudioInput работают без проблем на целочисленной PCM 8 и 16 бит. Единственное, в них не очень продуманная реализация, т.к. callback'и данных проходят через очередь сообщений потока (используются асинхронные сигналы), в котором живут QAudioOutput/QAudioInput, т.е. при прямом использовании из основного потока возможны задержки.

Попробуй сам преобразовать формат в PCM 8 или 16 и воспроизвести.   
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.12 секунд. Запросов: 22.