Итак, я экспериментировал с RtAudio и libsndfile.
Задача казалась простой:
1.) Считать некоторые примеры в буфер с помощью libsndfile (используя класс SndfileHandle и readf ()).
2.) Используйте RtAudio для воспроизведения сэмплов
НО, по какой-то причине, все, что я получаю, это шум и сильные искажения … Я попытался прочитать сэмплы как 16-битные PCM (используя короткий буфер) и использовать формат RTAUDIO_SINT16 для его воспроизведения. Безуспешно … На самом деле, я пробовал много разных комбинаций, и есть только шум …
Самое близкое к фактическому воспроизведению, которое я получил, было использование int16_t для буфера и RTAUDIO_SINT16. Кажется логичным, верно? Во всяком случае, это все равно, что использовать bitcrusher. Пробовал JACK и ALSA, и много разных комбинаций размера буфера, но безрезультатно …
Любой намек на то, как объединить эти два?
Может ли быть проблема в том, что я использую статический буфер (просто для экспериментов, конечно, не сделал бы это в конечном продукте …)?
Хорошо, отвечая на мой собственный вопрос, это была только путаница между некоторыми параметрами, в основном кадрами и сэмплами … в то время как сэмпл — это всего лишь один сэмпл, фрейм — это сэмплы всех каналов …
#include <iostream>
#include <sndfile.hh>
#include "RtAudio.h"
/*
* Audio-Wiedergabe mit RtAudio und libsndfile !
*/
// Call
int fplay( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *userData )
{int16_t *buffer = (int16_t *) outputBuffer;
// ok, i know this is not the best way to do file i/o in the audio thread, but
// this is just for demonstration purposes ...
SndfileHandle *sndfile = reinterpret_cast<SndfileHandle*>(userData);
// Error handling !
if ( status ){
std::cout << "Stream underflow detected!" << std::endl;
}// 'readf()' liest frames
// 'read()' liest einzelne Samples !
// ACHTUNG! Frames != Samples
// ein Frame = Samples für alle Kanäle
// d.h. |Samples| = Kanäle * Frames !
sndfile->readf(buffer, nBufferFrames);
return 0;
}
int main () {
// Damit das Programm funktioniert, muss eine 16Bit PCM Wave-Datei im
// gleichen Ordner liegen !
const char * fname = "test.wav" ;
// Soundfile-Handle aus der libsndfile-Bibliothek
SndfileHandle file = SndfileHandle (fname) ;
// Alle möglichen Infos über die Audio-Datei ausgeben !
std::cout << "Reading file: " << fname << std::endl;
std::cout << "File format: " << file.format() << std::endl;
std::cout << "PCM 16 BIT: " << (SF_FORMAT_WAV | SF_FORMAT_PCM_16) << std::endl;
std::cout << "Samples in file: " << file.frames() << std::endl;
std::cout << "Samplerate " << file.samplerate() << std::endl;
std::cout << "Channels: " << file.channels() << std::endl;
// Die RtAudio-Klasse ist gleichermassen dac und adc, wird hier aber nur als dac verwendet !
RtAudio dac;
if ( dac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
return 0;
}
// Output params ...
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 2;
parameters.firstChannel = 0;
unsigned int sampleRate = 44100;
// ACHTUNG! Frames != Samples
// ein Frame = Samples für alle Kanäle
// d.h. |Samples| = Kanäle*Frames !
unsigned int bufferFrames = 1024;try {
dac.openStream( ¶meters, NULL, RTAUDIO_SINT16,
sampleRate, &bufferFrames, &fplay, (void *)&file);
dac.startStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
return 0;
}
char input;
std::cout << "\nPlaying ... press <enter> to quit.\n";
std::cin.get( input );
try {
// Stop the stream
dac.stopStream();
}
catch (RtAudioError& e) {
e.printMessage();
}
if ( dac.isStreamOpen() ) dac.closeStream();
return 0 ;
}
Других решений пока нет …