Hi David, Attached is the output from
faust -a sndfile.cpp tmix2.dsp > tmix2.cpp for the Faust program (tmix2.dsp): // two-channel audio mixer: gain1 = hslider("Gain1",0.5,0,1,0.001); gain2 = hslider("Gain2",0.5,0,1,0.001); process = _, _ : *(gain1), *(gain2) :> _; (See tmix2.cpp attached) Cheers, - Julius On Fri, Feb 17, 2017 at 5:44 PM, David Griffith <d...@661.org> wrote: > > For a couple years I've been trying, without success, to reliably mix two > audio streams on the fly in C. I'm using libao, libmodplug, libsamplerate, > libsndfile, and libvorbis. The program is Frotz ( > https://github.com/DavidGriffith/frotz), a Z-machine emulator for playing > old Infocom games as well as newer ones. Could I please get some help with > this? > > > -- > David Griffith > d...@661.org > _______________________________________________ > Linux-audio-dev mailing list > Linux-audio-dev@lists.linuxaudio.org > http://lists.linuxaudio.org/listinfo/linux-audio-dev > -- Julius O. Smith III <j...@ccrma.stanford.edu> Professor of Music and, by courtesy, Electrical Engineering CCRMA, Stanford University http://ccrma.stanford.edu/~jos/ <http://ccrma.stanford.edu/>
//---------------------------------------------------------- // name: "tmix2" // // Code generated with Faust 0.9.96 (http://faust.grame.fr) //---------------------------------------------------------- /* link with */ /************************************************************************ IMPORTANT NOTE : this file contains two clearly delimited sections : the ARCHITECTURE section (in two parts) and the USER section. Each section is governed by its own copyright and license. Please check individually each section for license and copyright information. *************************************************************************/ /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/ /************************************************************************ FAUST Architecture File Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale --------------------------------------------------------------------- This Architecture section 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 3 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, see <http://www.gnu.org/licenses/>. EXCEPTION : As a special exception, you may create a larger work that contains this FAUST architecture section and distribute that work under terms of your choice, so long as this FAUST architecture section is not modified. ************************************************************************ ************************************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <limits.h> #include <math.h> #include <errno.h> #include <time.h> #include <sndfile.h> #include <vector> #include <stack> #include <string> #include <map> #include <iostream> #include "faust/gui/console.h" #include "faust/gui/FUI.h" #include "faust/dsp/dsp.h" #include "faust/misc.h" #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif #define READ_SAMPLE sf_readf_float //#define READ_SAMPLE sf_readf_double /****************************************************************************** ******************************************************************************* VECTOR INTRINSICS ******************************************************************************* *******************************************************************************/ /********************END ARCHITECTURE SECTION (part 1/2)****************/ /**************************BEGIN USER SECTION **************************/ #ifndef FAUSTFLOAT #define FAUSTFLOAT float #endif #ifndef FAUSTCLASS #define FAUSTCLASS mydsp #endif class mydsp : public dsp { private: FAUSTFLOAT fslider0; FAUSTFLOAT fslider1; int fSamplingFreq; public: virtual void metadata(Meta* m) { m->declare("name", "tmix2"); } virtual int getNumInputs() { return 2; } virtual int getNumOutputs() { return 1; } static void classInit(int samplingFreq) { } virtual void instanceConstants(int samplingFreq) { fSamplingFreq = samplingFreq; } virtual void instanceResetUserInterface() { fslider0 = 0.5f; fslider1 = 0.5f; } virtual void instanceClear() { } virtual void init(int samplingFreq) { classInit(samplingFreq); instanceInit(samplingFreq); } virtual void instanceInit(int samplingFreq) { instanceConstants(samplingFreq); instanceResetUserInterface(); instanceClear(); } virtual mydsp* clone() { return new mydsp(); } virtual int getSampleRate() { return fSamplingFreq; } virtual void buildUserInterface(UI* ui_interface) { ui_interface->openVerticalBox("0x00"); ui_interface->addHorizontalSlider("Gain1", &fslider0, 0.5f, 0.0f, 1.0f, 0.001f); ui_interface->addHorizontalSlider("Gain2", &fslider1, 0.5f, 0.0f, 1.0f, 0.001f); ui_interface->closeBox(); } virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) { float fSlow0 = float(fslider0); float fSlow1 = float(fslider1); FAUSTFLOAT* input0 = input[0]; FAUSTFLOAT* input1 = input[1]; FAUSTFLOAT* output0 = output[0]; for (int i=0; i<count; i++) { output0[i] = (FAUSTFLOAT)((fSlow0 * (float)input0[i]) + (fSlow1 * (float)input1[i])); } } }; /***************************END USER SECTION ***************************/ /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/ mydsp DSP; class Separator { int fNumFrames; int fNumInputs; int fNumOutputs; FAUSTFLOAT* fInput; FAUSTFLOAT* fOutputs[256]; public: Separator(int numFrames, int numInputs, int numOutputs) { fNumFrames = numFrames; fNumInputs = numInputs; fNumOutputs = max(numInputs, numOutputs); // allocate interleaved input channel fInput = (FAUSTFLOAT*) calloc(fNumFrames * fNumInputs, sizeof(FAUSTFLOAT)); // allocate separate output channels for (int i = 0; i < fNumOutputs; i++) { fOutputs[i] = (FAUSTFLOAT*) calloc (fNumFrames, sizeof(FAUSTFLOAT)); } } ~Separator() { // free interleaved input channel free(fInput); // free separate output channels for (int i = 0; i < fNumOutputs; i++) { free(fOutputs[i]); } } FAUSTFLOAT* input() { return fInput; } FAUSTFLOAT** outputs() { return fOutputs; } void separate() { for (int s = 0; s < fNumFrames; s++) { for (int c = 0; c < fNumInputs; c++) { fOutputs[c][s] = fInput[c + s*fNumInputs]; } } } }; class Interleaver { int fNumFrames; int fNumChans; FAUSTFLOAT* fInputs[256]; FAUSTFLOAT* fOutput; public: Interleaver(int numFrames, int numChans) { fNumFrames = numFrames; fNumChans = numChans; // allocate separate input channels for (int i = 0; i < fNumChans; i++) { fInputs[i] = (FAUSTFLOAT*) calloc (fNumFrames, sizeof(FAUSTFLOAT)); } // allocate interleaved output channel fOutput = (FAUSTFLOAT*) calloc(fNumFrames * fNumChans, sizeof(FAUSTFLOAT)); } ~Interleaver() { // free separate input channels for (int i = 0; i < fNumChans; i++) { free(fInputs[i]); } // free interleaved output channel free(fOutput); } FAUSTFLOAT** inputs() { return fInputs; } FAUSTFLOAT* output() { return fOutput; } void interleave() { for (int s = 0; s < fNumFrames; s++) { for (int c = 0; c < fNumChans; c++) { fOutput[c + s*fNumChans] = fInputs[c][s]; } } } }; #define kFrames 512 // loptrm : Scan command-line arguments and remove and return long int value when found long loptrm(int *argcP, char *argv[], const char* longname, const char* shortname, long def) { int argc = *argcP; for (int i=2; i<argc; i++) { if (strcmp(argv[i-1], shortname) == 0 || strcmp(argv[i-1], longname) == 0) { int optval = atoi(argv[i]); for (int j=i-1; j<argc-2; j++) { // make it go away for sake of "faust/gui/console.h" argv[j] = argv[j+2]; } *argcP -= 2; return optval; } } return def; } int main(int argc, char *argv[]) { SNDFILE* in_sf; SNDFILE* out_sf; SF_INFO in_info; SF_INFO out_info; unsigned int nAppend = 0; // number of frames to append beyond input file if (argc < 3) { fprintf(stderr,"*** USAGE: %s input_soundfile output_soundfile\n",argv[0]); exit(1); } nAppend = loptrm(&argc, argv, "--continue", "-c", 0); CMDUI* interface = new CMDUI(argc, argv); DSP.buildUserInterface(interface); interface->process_command(); // open input file in_info.format = 0; in_sf = sf_open(interface->input_file(), SFM_READ, &in_info); if (in_sf == NULL) { fprintf(stderr,"*** Input file not found.\n"); sf_perror(in_sf); exit(1); } // open output file out_info = in_info; out_info.format = in_info.format; out_info.channels = DSP.getNumOutputs(); out_sf = sf_open(interface->output_file(), SFM_WRITE, &out_info); if (out_sf == NULL) { fprintf(stderr,"*** Cannot write output file.\n"); sf_perror(out_sf); exit(1); } // create separator and interleaver Separator sep(kFrames, in_info.channels, DSP.getNumInputs()); Interleaver ilv(kFrames, DSP.getNumOutputs()); // init signal processor DSP.init(in_info.samplerate); //DSP.buildUserInterface(interface); interface->process_init(); // process all samples int nbf; do { nbf = READ_SAMPLE(in_sf, sep.input(), kFrames); sep.separate(); DSP.compute(nbf, sep.outputs(), ilv.inputs()); ilv.interleave(); sf_writef_float(out_sf, ilv.output(), nbf); //sf_write_raw(out_sf, ilv.output(), nbf); } while (nbf == kFrames); sf_close(in_sf); // compute tail, if any if (nAppend>0) { FAUSTFLOAT *input = (FAUSTFLOAT*) calloc(nAppend * DSP.getNumInputs(), sizeof(FAUSTFLOAT)); FAUSTFLOAT *inputs[1] = { input }; Interleaver ailv(nAppend, DSP.getNumOutputs()); DSP.compute(nAppend, inputs, ailv.inputs()); ailv.interleave(); sf_writef_float(out_sf, ailv.output(), nAppend); } sf_close(out_sf); } /********************END ARCHITECTURE SECTION (part 2/2)****************/
_______________________________________________ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/listinfo/linux-audio-dev