/* * Example 3: randomised realtime output using Portaudio * */ #include #include #include #include #include #include #include "guttersynth.h" #include "portaudio.h" #define NUM_SECONDS 60 #define SAMPLE_RATE 44100 #define FRAMES_PER_BUFFER 128 typedef struct { gutter_state *gs; long sample; long total_samples; double gamma[2]; double omega[2]; double c[2]; double dt[2]; double singleGain[2]; double* filterAutomation; } playstate; /* * Returns a random float within a range * * min: bottom end of range * max: top end of range * * returns: random float */ double rangerandom(double min, double max) { double random = ((double) rand()) / (double) RAND_MAX; double diff = max - min; double r = random * diff; return min + r; } double interpolate(double* items, int points, int point) { return (((items[1] - items[0]) / points) * point) + items[0]; } void rerandom(playstate* ps) { ps->gamma[0] = rangerandom(0.1, 10); ps->gamma[1] = rangerandom(0.1, 10); ps->omega[0] = rangerandom(0.01, 2); ps->omega[1] = rangerandom(0.01, 2); ps->c[0] = rangerandom(0.2, 2); ps->c[1] = rangerandom(0.2, 2); ps->dt[0] = rangerandom(400, 4000); ps->dt[1] = rangerandom(400, 4000); ps->singleGain[0] = rangerandom(0.2, 0.3); ps->singleGain[1] = rangerandom(0.2, 0.3); } static int audiocallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) { unsigned long i, sample; float audioSample; float *out = (float*)outputBuffer; playstate *ps = (playstate*) userData; gutter_state *gs = ps->gs; for (i = 0; i < framesPerBuffer; i++, ps->sample++) { if (ps->sample % SAMPLE_RATE == 0) { //gutter_randomisefilters(gs); //rerandom(ps); } int b, f, ix, ai; for (b = 0, ai = 0; b < gs->bankCount; b++) { for (f = 0; f < gs->filterCount; f++, ai=ai+6) { ix = b * gs->bankCount + f; gs->filterFreqs[ix] = interpolate(ps->filterAutomation + ai, ps->total_samples, ps->sample); gs->gains[ix] = interpolate(ps->filterAutomation + ai + 2, ps->total_samples, ps->sample); gs->Q[ix] = interpolate(ps->filterAutomation + ai + 4, ps->total_samples, ps->sample); } } gutter_calccoeffs(gs); gs->gamma = 7; //interpolate(ps->gamma, ps->total_samples, ps->sample); gs->omega = 1.2; //interpolate(ps->omega, ps->total_samples, ps->sample); gs->c = 0.5; //interpolate(ps->c, ps->total_samples, ps->sample); gs->dt = 500; //interpolate(ps->dt, ps->total_samples, ps->sample); gs->singleGain = 1; //interpolate(ps->singleGain, ps->total_samples, ps->sample); audioSample = (float) gutter_process(gs); *out++ = audioSample * 0.2; *out++ = audioSample * 0.2; } //ps->sample = ps->sample + framesPerBuffer; (void) timeInfo; /* Prevent unused variable warnings. */ (void) statusFlags; (void) inputBuffer; return paContinue; } int main() { // random seed from time srand((unsigned int) time(NULL)); playstate ps; ps.sample = 0; ps.total_samples = SAMPLE_RATE * NUM_SECONDS; ps.gs = gutter_init(2, 32, SAMPLE_RATE); ps.gs->filtersOn = 1; ps.gs->smoothing = 1; ps.gs->distortionMethod = 2; rerandom(&ps); ps.filterAutomation = malloc(sizeof(double) * ps.gs->bankCount * ps.gs->filterCount * 3 * 2); int b, f, i, ai; for (b = 0, ai=0; b < ps.gs->bankCount; b++) { for (f = 0; f < ps.gs->filterCount; f++) { i = b * ps.gs->bankCount + f; ps.filterAutomation[ai++] = rangerandom(100, 2000); ps.filterAutomation[ai++] = rangerandom(100, 2000); ps.filterAutomation[ai++] = rangerandom(0.6, 1); ps.filterAutomation[ai++] = rangerandom(0.6, 1); ps.filterAutomation[ai++] = rangerandom(20, 200); ps.filterAutomation[ai++] = rangerandom(20, 200); } } gutter_randomisefilters(ps.gs); PaStreamParameters outputParameters; PaStream *stream; PaError err; err = Pa_Initialize(); if (err != paNoError) { goto error; } outputParameters.device = Pa_GetDefaultOutputDevice(); if (outputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default output device.\n"); goto error; } outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ audiocallback, &ps); if (err != paNoError) goto error; //err = Pa_SetStreamFinishedCallback(stream, &StreamFinished); //if(err != paNoError) goto error; err = Pa_StartStream(stream); if(err != paNoError) goto error; printf("Play for %d seconds.\n", NUM_SECONDS); Pa_Sleep(NUM_SECONDS * 1000); err = Pa_StopStream( stream ); if(err != paNoError) goto error; err = Pa_CloseStream(stream); if(err != paNoError) goto error; Pa_Terminate(); printf("Example finished.\n"); free(ps.filterAutomation); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }