Skip to content
Snippets Groups Projects
Select Git revision
  • fad0fc7b273c39f6af67881a52a8171eb37b71ec
  • main default protected
  • 39-retour-utilisateur-sur-le-compteur
3 results

Display.java

Blame
  • 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;
    }