zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 2c133e58ced35c7747ddd74bdcf0d750566e8556
parent c24e6c76d4f74afda17513146066fd3727f2fc7a
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Mon,  3 May 2010 14:34:36 -0400

WIP: Wave Output in nio

Right now it glitches, but outputting something similar to desired

Diffstat:
Msrc/Misc/Recorder.cpp | 21+++++++--------------
Msrc/Misc/Recorder.h | 3---
Msrc/Nio/OutMgr.cpp | 7++++++-
Msrc/Nio/OutMgr.h | 3++-
Msrc/Nio/WavEngine.cpp | 74+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Msrc/Nio/WavEngine.h | 20++++++++++++++------
6 files changed, 82 insertions(+), 46 deletions(-)

diff --git a/src/Misc/Recorder.cpp b/src/Misc/Recorder.cpp @@ -22,11 +22,12 @@ #include <sys/stat.h> #include "Recorder.h" +#include "WavFile.h" #include "../Nio/OutMgr.h" #include "../Nio/WavEngine.h" Recorder::Recorder() - :status(0), wave(NULL), notetrigger(0) + :status(0), notetrigger(0) {} Recorder::~Recorder() @@ -45,8 +46,7 @@ int Recorder::preparefile(std::string filename_, int overwrite) return 1; } - if(!(wave=new WavEngine(sysOut, filename_, SAMPLE_RATE, 2))) - return 2; + sysOut->wave->newFile(new WavFile(filename_, SAMPLE_RATE, 2)); status = 1; //ready @@ -61,21 +61,15 @@ void Recorder::start() void Recorder::stop() { - if(wave) - { - //sysOut->remove(wave); - //wave->Stop(); - delete wave; - wave = NULL; //is this even needed? - } + sysOut->wave->Stop(); + sysOut->wave->destroyFile(); status = 0; } void Recorder::pause() { status = 0; - //wave->Stop(); - //sysOut->remove(wave); + sysOut->wave->Stop(); } int Recorder::recording() @@ -90,8 +84,7 @@ void Recorder::triggernow() { if(status == 2) { if(notetrigger!=1) { - //wave->openAudio(); - //sysOut->add(wave); + sysOut->wave->Start(); } notetrigger = 1; } diff --git a/src/Misc/Recorder.h b/src/Misc/Recorder.h @@ -25,8 +25,6 @@ #include <string> #include "../globals.h" -class WavEngine; - /**Records sound to a file*/ class Recorder { @@ -50,7 +48,6 @@ class Recorder int status; private: - WavEngine *wave; int notetrigger; }; diff --git a/src/Nio/OutMgr.cpp b/src/Nio/OutMgr.cpp @@ -5,6 +5,7 @@ #include "Engine.h" #include "EngineMgr.h" #include "InMgr.h" +#include "WavEngine.h" #include "../Misc/Master.h" #include "../Misc/Util.h"//for set_realtime() @@ -13,7 +14,8 @@ using namespace std; OutMgr *sysOut; OutMgr::OutMgr(Master *nmaster) - :priBuf(new REALTYPE[4096],new REALTYPE[4096]),priBuffCurrent(priBuf) + :wave(new WavEngine(this)), + priBuf(new REALTYPE[4096],new REALTYPE[4096]),priBuffCurrent(priBuf) { currentOut = NULL; stales = 0; @@ -148,6 +150,9 @@ string OutMgr::getSink() const void OutMgr::addSmps(REALTYPE *l, REALTYPE *r) { + //allow wave file to syphon off stream + wave->push(Stereo<REALTYPE *>(l,r),SOUND_BUFFER_SIZE); + Stereo<Sample> smps(Sample(SOUND_BUFFER_SIZE, l), Sample(SOUND_BUFFER_SIZE, r)); if(currentOut->getSampleRate() != SAMPLE_RATE) { //we need to resample diff --git a/src/Nio/OutMgr.h b/src/Nio/OutMgr.h @@ -43,6 +43,8 @@ class OutMgr bool setSink(std::string name); std::string getSink() const; + + WavEngine *wave; /**<The Wave Recorder*/ private: void addSmps(REALTYPE *l, REALTYPE *r); int storedSmps() const {return priBuffCurrent.l() - priBuf.l();}; @@ -53,7 +55,6 @@ class OutMgr AudioOut *currentOut;/**<The current output driver*/ - WavEngine *wave; /**<The Wave Recorder*/ sem_t requested; /**Buffer*/ diff --git a/src/Nio/WavEngine.cpp b/src/Nio/WavEngine.cpp @@ -20,47 +20,81 @@ #include <cstdio> #include <iostream> #include <cstdlib> -#include "SafeQueue.h" +#include "../Misc/WavFile.h" #include "../Misc/Util.h" using namespace std; -WavEngine::WavEngine(OutMgr *out, string filename, int samplerate, int channels) - :AudioOut(out), file(filename, samplerate, channels), - enabled(false) +WavEngine::WavEngine(OutMgr *out) + :AudioOut(out), file(NULL), buffer(SAMPLE_RATE*2), pThread(NULL) { + sem_init(&work, PTHREAD_PROCESS_PRIVATE, 0); } WavEngine::~WavEngine() { Stop(); + sem_destroy(&work); + destroyFile(); } bool WavEngine::openAudio() { - return file.good(); + return file && file->good(); } bool WavEngine::Start() { - if(enabled()) + if(pThread) return true; + pThread = new pthread_t; + pthread_attr_t attr; - enabled = true; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_create(&pThread, &attr, _AudioThread, this); + pthread_create(pThread, &attr, _AudioThread, this); return true; } void WavEngine::Stop() { - if(!enabled()) + if(!pThread) + return; + + pthread_t *tmp = pThread; + pThread = NULL; + + sem_post(&work); + pthread_join(*tmp, NULL); + delete pThread; +} + +void WavEngine::push(Stereo<REALTYPE *> smps, size_t len) +{ + if(!pThread) return; - enabled = false; - pthread_join(pThread, NULL); + + //copy the input [overflow when needed] + for(size_t i = 0; i < len; ++i) { + buffer.push(*smps.l()++); + buffer.push(*smps.r()++); + sem_post(&work); + } +} + +void WavEngine::newFile(WavFile *_file) +{ + //ensure system is clean + destroyFile(); + file = _file; +} + +void WavEngine::destroyFile() +{ + if(file) + delete file; } void *WavEngine::_AudioThread(void *arg) @@ -70,18 +104,16 @@ void *WavEngine::_AudioThread(void *arg) void *WavEngine::AudioThread() { - short int *recordbuf_16bit = new short int [SOUND_BUFFER_SIZE*2]; - int size = SOUND_BUFFER_SIZE; - + short int recordbuf_16bit[2]; - while (enabled()) + while(!sem_wait(&work) && pThread) { - const Stereo<Sample> smps = getNext(true); - for(int i = 0; i < size; i++) { - recordbuf_16bit[i*2] = limit((int)(smps.l()[i] * 32767.0), -32768, 32767); - recordbuf_16bit[i*2+1] = limit((int)(smps.r()[i] * 32767.0), -32768, 32767); - } - file.writeStereoSamples(size, recordbuf_16bit); + float left=0.0f, right=0.0f; + buffer.pop(left); + buffer.pop(right); + recordbuf_16bit[0] = limit((int)(left * 32767.0), -32768, 32767); + recordbuf_16bit[1] = limit((int)(right * 32767.0), -32768, 32767); + file->writeStereoSamples(1, recordbuf_16bit); } pthread_exit(NULL); } diff --git a/src/Nio/WavEngine.h b/src/Nio/WavEngine.h @@ -23,15 +23,16 @@ #ifndef WAVENGINE_H #define WAVENGINE_H #include "AudioOut.h" -#include "../Misc/WavFile.h" -#include "../Misc/Atomic.h" #include <string> #include <pthread.h> +#include <semaphore.h> +#include "SafeQueue.h" +class WavFile; class WavEngine: public AudioOut { public: - WavEngine(OutMgr *out, std::string filename, int samplerate, int channels); + WavEngine(OutMgr *out); ~WavEngine(); bool openAudio(); @@ -41,14 +42,21 @@ class WavEngine: public AudioOut void setAudioEn(bool /*nval*/){}; bool getAudioEn() const{return true;}; + void push(Stereo<REALTYPE *> smps, size_t len); + + void newFile(WavFile *_file); + void destroyFile(); + protected: void *AudioThread(); static void *_AudioThread(void *arg); private: - WavFile file; - Atomic<bool> enabled; - pthread_t pThread; + WavFile *file; + sem_t work; + SafeQueue<float> buffer; + + pthread_t *pThread; }; #endif