Select Git revision
Display.java
-
Kellian Mirey authoredKellian Mirey authored
AudioManager.cpp 5.03 KiB
/***************************************************************************
* AudioManager.cpp
* Part of Rivill
* 2015- Florent Berthaut / Luka Claeys
* https://gitlab.univ-lille.fr/mint/rivill
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "AudioManager.hpp"
void* audioThreadFunction(void* pvParam) {
AudioManager *pThis=(AudioManager*)pvParam;
pThis->startStream();
return 0;
}
AudioManager* AudioManager::getInstance() {
static AudioManager rev;
return &rev;
}
AudioManager::~AudioManager() {}
int AudioManager::getRate(){
return data.nRate;
}
int AudioManager::getBufferSize(){
return m_bufSize;
}
int AudioManager::getMixSize(){
return data.mixSize;
}
int AudioManager::rtaudio_callback(void *outbuf, void *inbuf, unsigned int nFrames,
double streamtime, RtAudioStreamStatus status, void *userdata) {
(void)inbuf;
float *buf = (float*)outbuf;
AudioManager::CallbackData *data = (AudioManager::CallbackData*) userdata;
//if we've reached the first buffer again, retrieve values from the ring
if(data->bufCounter==0) {
if(ringbuffer_read_space(data->ringBuffer) >= data->bufSize) {
//read all the audio values
ringbuffer_read(data->ringBuffer, data->buffer, data->bufSize);
//mix the first buffer with the last of the previous
float step = 1.0/float(nFrames);
float cnt = 0.0;
for(int i=0; i < nFrames; ++i) {
buf[i*2] = data->buffer[i]*cnt + data->mixBuffer[i]*(1.0-cnt);
buf[i*2+1] = buf[i*2];
cnt+=step;
}
//save the last buffer for crossfading
memcpy(&data->mixBuffer[0],
data->buffer+(data->bufSize-data->mixSize),
data->mixSize*sizeof(float));
}
else {
memset(buf, 0, nFrames*data->nChannel*sizeof(float));
memset(data->buffer, 0, data->bufSize*sizeof(float));
memset(data->mixBuffer, 0, nFrames*sizeof(float));
//cout<<"AudioManager : Could not read buffer"<<endl;
}
}
else {
//read the next buffer
for(int i=0; i<nFrames; ++i) {
buf[i*2] = data->buffer[data->bufCounter*nFrames+i];
buf[i*2+1] = buf[i*2];
}
}
//move to the next buffer
data->bufCounter=(data->bufCounter+1)%(data->nbBufs-1);
return 0;
}
AudioManager::AudioManager() {
m_init=false;
}
void AudioManager::init() {
//m_rtAudio = new RtAudio(RtAudio::LINUX_PULSE);
m_rtAudio = new RtAudio(RtAudio::UNIX_JACK);
param = new RtAudio::StreamParameters();
param->deviceId = m_rtAudio->getDefaultOutputDevice();
param->nChannels = 2;
options = new RtAudio::StreamOptions();
options->streamName = "Rivill";
data.nRate = m_rtAudio->getDeviceInfo(param->deviceId).preferredSampleRate;
m_rtBufSize = 1024;
bool init=true;
try{
m_rtAudio->openStream(param, NULL, RTAUDIO_FLOAT32, data.nRate,
&m_rtBufSize,
AudioManager::rtaudio_callback, &data, options);
}
catch(const exception& e) {
init=false;
}
if(init) {
int nbBufs = 6-m_rtBufSize/256;
m_bufSize = m_rtBufSize*nbBufs;
data.ringBuffer = ringbuffer_create(m_bufSize*3);
data.nChannel = param->nChannels;
data.bufSize = m_bufSize;
data.buffer = new float[m_bufSize];
data.nbBufs = nbBufs;
data.bufCounter = 0;
memset(&data.buffer[0], 0, data.bufSize*sizeof(float));
data.mixSize = m_rtBufSize;
data.mixBuffer = new float[data.mixSize];
memset(&data.mixBuffer[0], 0, data.mixSize*sizeof(float));
m_thread = new std::thread(audioThreadFunction, this);
m_init = true;
}
}
bool AudioManager::changeBuf(float* outputBuf, float maxSinValue) {
if(m_init) {
//check if there is space to write the new values
size_t write_space = ringbuffer_write_space(data.ringBuffer);
if(write_space >= m_bufSize) {
//write all data to the ringbuffer
ringbuffer_write(data.ringBuffer, outputBuf, data.bufSize);
return true;
}
else {
//cout<<"AudioManager : Could not write buffer"<<endl;
}
}
return false;
}