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 <[email protected]> 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
> [email protected]
> _______________________________________________
> Linux-audio-dev mailing list
> [email protected]
> http://lists.linuxaudio.org/listinfo/linux-audio-dev
>
--
Julius O. Smith III <[email protected]>
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
[email protected]
http://lists.linuxaudio.org/listinfo/linux-audio-dev