// Call int fplay( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void *userData ) { // Da wir RTAUDIO_SINT16 als Format angegeben haben, macht dieser Datentyp // Sinn ! Btw: Bei Inkompatiblen Datentypen können sich ebenfalls "interessante" // Effekte ergeben ! int16_t *buffer = (int16_t *) outputBuffer; // Daten zurückcasten ... 'reinterpret_cast' hat keine Sicherheitsbedenken und castet alles // in alles andere ! SndfileHandle *sndfile = reinterpret_cast<SndfileHandle*>(userData); // Error handling ! if ( status ){ std::cout << "Stream underflow detected!" << std::endl; } // Direkt aus der Soundfile in den OutputBuffer lesen! // Für das Beispiel reicht das, allerdings sollte man in einem 'ernsthaften' Programm // eine andere Lösung finden. Disk I/O ist auch in Zeiten der SSDs eher langsam und // sollte nicht direkt im Audio-Thread stattfinden ! // '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; }
//-------------------------------------------------------------- void ofxAudioSample::load(string tmpPath, float _hSampleRate) { myPath = ofToDataPath(tmpPath,true).c_str(); SndfileHandle sndFile = SndfileHandle(myPath); myFormat = sndFile.format(); myChannels = sndFile.channels(); mySampleRate = sndFile.samplerate(); resampligFactor = _hSampleRate/mySampleRate; speed = mainSpeed/resampligFactor; bufferSize = 4096 * myChannels; readBuffer = new float[bufferSize]; ofVec2f _wF; int readcount; int readpointer; // convert all multichannel files to mono by averaging the channels float monoAverage; while(readcount = sndFile.readf(readBuffer, 4096)){ readpointer = 0; _wF.set(0,0); for (int i = 0; i < readcount; i++) { // for each frame... monoAverage = 0; for(int j = 0; j < myChannels; j++) { monoAverage += readBuffer[readpointer + j]; } monoAverage /= myChannels; readpointer += myChannels; // add the averaged sample to our vector of samples samples.push_back(monoAverage); // add to the waveform data _wF.x = MIN(_wF.x, monoAverage); _wF.y = MAX(_wF.y, monoAverage); } _waveForm.push_back(_wF); } position = 0; }