zynaddsubfx

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

WavEngine.cpp (2879B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   WavEngine - an Output To File Engine
      5   Copyright (C) 2006 Nasca Octavian Paul
      6   Author: Nasca Octavian Paul
      7 
      8   This program is free software; you can redistribute it and/or
      9   modify it under the terms of the GNU General Public License
     10   as published by the Free Software Foundation; either version 2
     11   of the License, or (at your option) any later version.
     12 */
     13 
     14 #include "WavEngine.h"
     15 #include <cstdio>
     16 #include <iostream>
     17 #include <cstdlib>
     18 #include "../Misc/WavFile.h"
     19 #include "../Misc/Util.h"
     20 using namespace std;
     21 
     22 namespace zyn {
     23 
     24 WavEngine::WavEngine(const SYNTH_T &synth_)
     25     :AudioOut(synth_), file(NULL), buffer(synth.samplerate * 4), pThread(NULL)
     26 {
     27     work.init(PTHREAD_PROCESS_PRIVATE, 0);
     28 }
     29 
     30 WavEngine::~WavEngine()
     31 {
     32     Stop();
     33     destroyFile();
     34 }
     35 
     36 bool WavEngine::openAudio()
     37 {
     38     return file && file->good();
     39 }
     40 
     41 bool WavEngine::Start()
     42 {
     43     if(pThread)
     44         return true;
     45     pThread = new pthread_t;
     46 
     47     pthread_attr_t attr;
     48     pthread_attr_init(&attr);
     49     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
     50     pthread_create(pThread, &attr, _AudioThread, this);
     51 
     52     return true;
     53 }
     54 
     55 void WavEngine::Stop()
     56 {
     57     if(!pThread)
     58         return;
     59 
     60     pthread_t *tmp = pThread;
     61     pThread = NULL;
     62 
     63     work.post();
     64     pthread_join(*tmp, NULL);
     65     delete pThread;
     66     destroyFile();
     67 }
     68 
     69 void WavEngine::push(Stereo<float *> smps, size_t len)
     70 {
     71     if(!pThread)
     72         return;
     73 
     74 
     75     //copy the input [overflow when needed]
     76     for(size_t i = 0; i < len; ++i) {
     77         buffer.push(*smps.l++);
     78         buffer.push(*smps.r++);
     79     }
     80     work.post();
     81 }
     82 
     83 void WavEngine::newFile(WavFile *_file)
     84 {
     85     //ensure system is clean
     86     destroyFile();
     87     file = _file;
     88 
     89     //check state
     90     if(!file->good())
     91         cerr
     92         << "ERROR: WavEngine handed bad file output WavEngine::newFile()"
     93         << endl;
     94 }
     95 
     96 void WavEngine::destroyFile()
     97 {
     98     if(file)
     99         delete file;
    100     file = NULL;
    101 }
    102 
    103 void *WavEngine::_AudioThread(void *arg)
    104 {
    105     return (static_cast<WavEngine *>(arg))->AudioThread();
    106 }
    107 
    108 void *WavEngine::AudioThread()
    109 {
    110     short *recordbuf_16bit = new short[2 * synth.buffersize];
    111 
    112     while(!work.wait() && pThread) {
    113         for(int i = 0; i < synth.buffersize; ++i) {
    114             float left = 0.0f, right = 0.0f;
    115             buffer.pop(left);
    116             buffer.pop(right);
    117             recordbuf_16bit[2 * i] = limit((int)(left * 32767.0f),
    118                                            -32768,
    119                                            32767);
    120             recordbuf_16bit[2 * i + 1] = limit((int)(right * 32767.0f),
    121                                                -32768,
    122                                                32767);
    123         }
    124         if(file)
    125             file->writeStereoSamples(synth.buffersize, recordbuf_16bit);
    126     }
    127 
    128     delete[] recordbuf_16bit;
    129 
    130     return NULL;
    131 }
    132 
    133 }