/* Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "artsflow.h" #include "debug.h" #include "convert.h" #include "objectmanager.h" #include "audiosubsys.h" #include "dispatcher.h" #include "iomanager.h" #include "flowsystem.h" #include "stdsynthmodule.h" #include <stdio.h> #include <iostream> #include <cstring> #undef DEBUG_WAVEFORM #ifdef DEBUG_WAVEFORM #include <fstream> #endif using namespace std; using namespace Arts; namespace Arts { class Synth_RECORD_impl : virtual public Synth_RECORD_skel, virtual public ASConsumer, virtual public StdSynthModule { #ifdef DEBUG_WAVEFORM ofstream plotfile; #endif protected: AudioSubSystem *as; bool haveSubSys; typedef unsigned char uchar; unsigned char *inblock; unsigned long maxsamples; unsigned long channels; int format; int bits; public: #ifdef DEBUG_WAVEFORM Synth_RECORD_impl() : plotfile( "/dev/shm/synth_record.plot" ) { } #endif /* * functions from the SynthModule interface (which is inherited by * SynthPlay) */ void streamInit() { as = AudioSubSystem::the(); channels = as->channels(); format = as->format(); bits = as->bits(); maxsamples = 0; inblock = 0; haveSubSys = as->attachConsumer(this); if(!haveSubSys) { arts_info("Synth_RECORD: audio subsystem is already used"); return; } } void streamEnd() { arts_debug("Synth_RECORD: detaching"); if(haveSubSys) as->detachConsumer(); if(inblock) { delete[] inblock; inblock = 0; } } AutoSuspendState autoSuspend() { return static_cast<AutoSuspendState>(asSuspend|asProducer); } void calculateBlock(unsigned long samples) { // no audio subsystem, no play if(!as->running() || !haveSubSys) return; if(samples > maxsamples) { maxsamples = samples; if(inblock) delete[] inblock; inblock = new uchar[maxsamples * channels * bits / 8]; } assert(channels); as->read(inblock,channels * (bits/8) * samples); arts_assert(format == 8 || format == 16 || format == 17 || format == 32); if(format == 8) { if(channels == 1) convert_mono_8_float(samples,inblock,left); if(channels == 2) convert_stereo_i8_2float(samples,inblock,left,right); } else if(format == 16) { if(channels == 1) convert_mono_16le_float(samples,inblock,left); if(channels == 2) convert_stereo_i16le_2float(samples,inblock,left,right); } else if(format == 17) { if(channels == 1) convert_mono_16be_float(samples,inblock,left); if(channels == 2) convert_stereo_i16be_2float(samples,inblock,left,right); } else if(format == 32) { if(channels == 2) { float * end = (float *)(inblock + 8 * samples); float * floatbuffer = (float *)inblock; while(floatbuffer < end) { #ifdef DEBUG_WAVEFORM plotfile << *floatbuffer << "\n"; #endif *left++ = *floatbuffer++; *right++ = *floatbuffer++; } } else if(channels == 1) memcpy(left, inblock, samples); } } /** * havemore from the ASConsumer interface (AudioSubSystem) */ void haveMore() { _node()->requireFlow(); } }; REGISTER_IMPLEMENTATION(Synth_RECORD_impl); } // vim: sw=4 ts=4