diff --git a/.gitmodules b/.gitmodules index 35e4876..3524c3c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "colorchord2/rawdraw"] path = colorchord2/rawdraw url = https://github.com/cntools/rawdraw +[submodule "colorchord2/cnfa"] + path = colorchord2/cnfa + url = https://github.com/cnlohr/cnfa diff --git a/colorchord2/Makefile b/colorchord2/Makefile index 3d992a5..6854d63 100644 --- a/colorchord2/Makefile +++ b/colorchord2/Makefile @@ -1,29 +1,26 @@ all : colorchord -RAWDRAW:=DrawFunctions.o XDriver.o -SOUND:=sound.o sound_alsa.o sound_pulse.o sound_null.o - OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayDMX.o OutputProminent.o RecorderPlugin.o DisplayHIDAPI.o hidapi.o OutputCells.o DisplaySHM.o DisplayFileWrite.o WINGCC:= i686-w64-mingw32-gcc -WINGCCFLAGS:= -g -DICACHE_FLASH_ATTR= -I../embeddedcommon -I. -O1 #-O2 -Wl,--relax -Wl,--gc-sections -ffunction-sections -fdata-sections +WINGCCFLAGS:= -g -DICACHE_FLASH_ATTR= -I../embeddedcommon -Icnfa -Irawdraw -I. -O1 #-O2 -Wl,--relax -Wl,--gc-sections -ffunction-sections -fdata-sections WINLDFLAGS:=-lwinmm -lgdi32 -lws2_32 -lsetupapi RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse -ludev -lrt -CFLAGS:=-g -O1 -flto -Wall -ffast-math -I../embeddedcommon -I. -DICACHE_FLASH_ATTR= +CFLAGS:=-g -O1 -flto -Wall -ffast-math -I../embeddedcommon -I. -Icnfa -Irawdraw -DICACHE_FLASH_ATTR= EXTRALIBS:=-lusb-1.0 -OBJS:=os_generic.o main.o dft.o decompose.o filter.o color.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o hook.o ../embeddedcommon/DFT32.o configs.o +OBJS:=os_generic.o main.o dft.o decompose.o filter.o color.o notefinder.o util.o outdrivers.o $(OUTS) parameters.o chash.o hook.o ../embeddedcommon/DFT32.o configs.o colorchord : $(OBJS) gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS) -colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c OutputProminent.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c hook.c RecorderPlugin.c ../embeddedcommon/DFT32.c OutputCells.c configs.c hidapi.c DisplayHIDAPI.c +colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c notefinder.c util.c outdrivers.c parameters.c chash.c OutputVoronoi.c OutputProminent.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c hook.c RecorderPlugin.c ../embeddedcommon/DFT32.c OutputCells.c configs.c hidapi.c DisplayHIDAPI.c $(WINGCC) $(WINGCCFLAGS) -o $@ $^ $(WINLDFLAGS) diff --git a/colorchord2/RecorderPlugin.c b/colorchord2/RecorderPlugin.c index 25ff7cb..220f325 100644 --- a/colorchord2/RecorderPlugin.c +++ b/colorchord2/RecorderPlugin.c @@ -107,7 +107,7 @@ void StartRecording( struct RecorderPlugin * rp ) } -static void RecordEvent(void * v, int samples, float * samps, int channel_ct) +static void RecordEvent(void * v, int samples, short * samps, int channel_ct) { struct RecorderPlugin * rp = (struct RecorderPlugin*)v; @@ -115,7 +115,7 @@ static void RecordEvent(void * v, int samples, float * samps, int channel_ct) if( rp->DunBoop || !rp->fPlay ) { - int r = fwrite( samps, channel_ct * sizeof( float ), samples, rp->fRec ); + int r = fwrite( samps, channel_ct * sizeof( short ), samples, rp->fRec ); if( r != samples ) { StopRecording( rp ); @@ -123,12 +123,12 @@ static void RecordEvent(void * v, int samples, float * samps, int channel_ct) } } -static void PlaybackEvent(void * v, int samples, float * samps, int channel_ct) +static void PlaybackEvent(void * v, int samples, short * samps, int channel_ct) { struct RecorderPlugin * rp = (struct RecorderPlugin*)v; if( !rp->fPlay ) return; - int r = fread( samps, channel_ct * sizeof( float ), samples, rp->fPlay ); + int r = fread( samps, channel_ct * sizeof( short ), samples, rp->fPlay ); if( r != samples ) { StopRecording( rp ); @@ -143,7 +143,7 @@ static void PlaybackEvent(void * v, int samples, float * samps, int channel_ct) else force_white = 0; - int r = fwrite( samps, channel_ct * sizeof( float ), samples, rp->fRec ); + int r = fwrite( samps, channel_ct * sizeof( short ), samples, rp->fRec ); if( r != samples ) { StopRecording( rp ); diff --git a/colorchord2/cnfa b/colorchord2/cnfa new file mode 160000 index 0000000..22f0e58 --- /dev/null +++ b/colorchord2/cnfa @@ -0,0 +1 @@ +Subproject commit 22f0e58a4df57c6a6b5fa05665a6d454e597e2da diff --git a/colorchord2/colorchord.exe b/colorchord2/colorchord.exe index f773c09..80f46ba 100755 Binary files a/colorchord2/colorchord.exe and b/colorchord2/colorchord.exe differ diff --git a/colorchord2/hook.c b/colorchord2/hook.c index dfba8d8..1f03a03 100644 --- a/colorchord2/hook.c +++ b/colorchord2/hook.c @@ -54,14 +54,14 @@ void UnhookKeyEvent( void (*KeyE)( void * v, int key, int down ), void * v ) struct SoundEvent { - void (*SoundE)( void * v, int samples, float * samps, int channel_ct ); + void (*SoundE)( void * v, int samples, short * samps, int channel_ct ); void * v; }; struct SoundEvent SoundEvents[2][MAX_SOUND_EVENTS]; -void SoundEventHappened( int samples, float * samps, int is_out, int channel_ct ) +void SoundEventHappened( int samples, short * samps, int is_out, int channel_ct ) { int i; for( i = 0; i < MAX_SOUND_EVENTS; i++ ) @@ -73,7 +73,7 @@ void SoundEventHappened( int samples, float * samps, int is_out, int channel_ct } } -void HookSoundInEvent( void (*SoundE)( void * v, int samples, float * samps, int channel_ct ), void * v, int is_out ) +void HookSoundInEvent( void (*SoundE)( void * v, int samples, short * samps, int channel_ct ), void * v, int is_out ) { int i; for( i = 0; i < MAX_SOUND_EVENTS; i++ ) @@ -87,7 +87,7 @@ void HookSoundInEvent( void (*SoundE)( void * v, int samples, float * samps, int } } -void UnhookSoundInEvent( void (*SoundE)( void * v, int samples, float * samps, int channel_ct ), void * v, int is_out ) +void UnhookSoundInEvent( void (*SoundE)( void * v, int samples, short * samps, int channel_ct ), void * v, int is_out ) { int i; for( i = 0; i < MAX_SOUND_EVENTS; i++ ) diff --git a/colorchord2/hook.h b/colorchord2/hook.h index 81afa1c..cdac7d9 100644 --- a/colorchord2/hook.h +++ b/colorchord2/hook.h @@ -11,9 +11,9 @@ void HookKeyEvent( void (*KeyEvent)( void * v, int key, int down ), void * v ); void UnhookKeyEvent( void (*KeyEvent)( void * v, int key, int down ), void * v ); -void SoundEventHappened( int samples, float * samps, int channel_ct, int is_out ); -void HookSoundInEvent( void (*SoundE)( void * v, int samples, float * samps, int channel_ct ), void * v, int is_out ); -void UnhookSoundInEvent( void (*SoundE)( void * v, int samples, float * samps, int channel_ct ), void * v, int is_out ); +void SoundEventHappened( int samples, short * samps, int channel_ct, int is_out ); +void HookSoundInEvent( void (*SoundE)( void * v, int samples, short * samps, int channel_ct ), void * v, int is_out ); +void UnhookSoundInEvent( void (*SoundE)( void * v, int samples, short * samps, int channel_ct ), void * v, int is_out ); #endif diff --git a/colorchord2/main.c b/colorchord2/main.c index da04f2a..e7aab7c 100644 --- a/colorchord2/main.c +++ b/colorchord2/main.c @@ -1,12 +1,15 @@ //Copyright 2015 <>< Charles Lohr under the ColorChord License. +#if defined(WIN32) || defined(USE_WINDOWS) +#include +#include +#endif + #include #include "color.h" #include #include -#include "sound.h" #include "os_generic.h" -#include "DrawFunctions.h" #include "dft.h" #include "filter.h" #include "decompose.h" @@ -18,6 +21,19 @@ #include "hook.h" #include "configs.h" + +#define CNFG_IMPLEMENTATION +#include "CNFG.h" + +#define CNFA_IMPLEMENTATION +#include "CNFA.h" + + + +//Sound driver. +struct CNFADriver * sd; + + #ifdef ANDROID #include #include @@ -25,7 +41,6 @@ #include #include #include - static int pfd[2]; static pthread_t loggingThread; static const char *LOG_TAG = "colorchord"; @@ -45,28 +60,28 @@ static void *loggingFunction(void*v) { return 0; } - #endif - -struct SoundDriver * sd; + + #if defined(WIN32) || defined(USE_WINDOWS) -#include -#include #define ESCAPE_KEY 0x1B -void WindowsTerm() +void HandleDestroy() { - CloseSound( sd ); + CNFAClose( sd ); } + #else #define ESCAPE_KEY 65307 #endif + + float DeltaFrameTime = 0; double Now = 0; @@ -124,10 +139,10 @@ void HandleMotion( int x, int y, int mask ) { } -void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct SoundDriver * sd ) +void SoundCB( struct CNFADriver * sd, short * in, short * out, int samplesr, int samplesp ) { int channelin = sd->channelsRec; -// int channelout = sd->channelsPlay; + int channelout = sd->channelsPlay; //*samplesp = 0; // int process_channels = (MAX_CHANNELS < channelin)?MAX_CHANNELS:channelin; @@ -136,60 +151,61 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun int i; int j; - for( i = 0; i < samplesr; i++ ) + if( in ) { - if( out ) + for( i = 0; i < samplesr; i++ ) { - for( j = 0; j < channelin; j++ ) + if( sample_channel < 0 ) { - out[i*channelin+j] = 0; - } - } + float fo = 0; + for( j = 0; j < channelin; j++ ) + { + float f = in[i*channelin+j] / 32767.; + if( f >= -1 && f <= 1 ) + { + fo += f; + } + else + { + fo += (f>0)?1:-1; + // printf( "Sound fault A %d/%d %d/%d %f\n", j, channelin, i, samplesr, f ); + } + } - if( sample_channel < 0 ) - { - float fo = 0; - for( j = 0; j < channelin; j++ ) + fo /= channelin; + sound[soundhead] = fo*in_amplitude; + soundhead = (soundhead+1)%SOUNDCBSIZE; + } + else { - float f = in[i*channelin+j]; - if( f >= -1 && f <= 1 ) - { - fo += f; - } - else - { - fo += (f>0)?1:-1; -// printf( "Sound fault A %d/%d %d/%d %f\n", j, channelin, i, samplesr, f ); + float f = in[i*channelin+sample_channel] / 32767.; + + if( f > 1 || f < -1 ) + { + f = (f>0)?1:-1; } + + + //printf( "Sound fault B %d/%d\n", i, samplesr ); + sound[soundhead] = f*in_amplitude; + soundhead = (soundhead+1)%SOUNDCBSIZE; + } - - fo /= channelin; - sound[soundhead] = fo*in_amplitude; - soundhead = (soundhead+1)%SOUNDCBSIZE; - } - else - { - float f = in[i*channelin+sample_channel]; - - if( f > 1 || f < -1 ) - { - f = (f>0)?1:-1; - } - - - //printf( "Sound fault B %d/%d\n", i, samplesr ); - sound[soundhead] = f*in_amplitude; - soundhead = (soundhead+1)%SOUNDCBSIZE; - } + SoundEventHappened( samplesr, in, 0, channelin ); } - SoundEventHappened( samplesr, in, 0, channelin ); + if( out ) { + for( j = 0; j < samplesp * channelout; j++ ) + { + out[j] = 0; + } SoundEventHappened( samplesr, out, 1, sd->channelsPlay ); } - *samplesp = samplesr; + + } #ifdef ANDROID @@ -309,7 +325,9 @@ int main(int argc, char ** argv) //Initialize Sound - sd = InitSound( sound_source, &SoundCB ); + sd = CNFAInit( sound_source, "colorchord", &SoundCB, GetParameterI( "samplerate", 44100 ), + GetParameterI( "channels", 2 ), GetParameterI( "channels", 2 ), GetParameterI( "buffer", 1024 ), + GetParameterS( "devrecord", 0 ), GetParameterS( "devplay", 0 ) ); if( !sd ) { @@ -317,7 +335,7 @@ int main(int argc, char ** argv) return -1; } - nf = CreateNoteFinder( sd->spsRec ); + nf = CreateNoteFinder( sd->sps ); //Once everything was reinitialized, re-read the ini files. SetEnvValues( 1 ); diff --git a/colorchord2/rawdraw b/colorchord2/rawdraw index e5acb75..55fa52d 160000 --- a/colorchord2/rawdraw +++ b/colorchord2/rawdraw @@ -1 +1 @@ -Subproject commit e5acb751f337f3ae9e558e98907be8e3d6f8381f +Subproject commit 55fa52d1eb355baf1456aa55251e722500a32ab8 diff --git a/colorchord2/sound.c b/colorchord2/sound.c deleted file mode 100644 index 9f03707..0000000 --- a/colorchord2/sound.c +++ /dev/null @@ -1,108 +0,0 @@ -//Copyright 2015 <>< Charles Lohr under the ColorChord License. - -#include "sound.h" -#include -#include -#include - -static SoundInitFn * SoundDrivers[MAX_SOUND_DRIVERS]; -static char * SoundDriverNames[MAX_SOUND_DRIVERS]; //XXX: There's a bug in my compiler, this should be 'static' -static int SoundDriverPriorities[MAX_SOUND_DRIVERS]; -/* -void CleanupSound() __attribute__((destructor)); -void CleanupSound() -{ - int i; - for( i = 0; i < MAX_SOUND_DRIVERS; i++ ) - { - if( SoundDriverNames[i] ) - { - free( SoundDriverNames[i] ); - } - } -} -*/ - -void RegSound( int priority, const char * name, SoundInitFn * fn ) -{ - int j; - - if( priority <= 0 ) - { - return; - } - - for( j = MAX_SOUND_DRIVERS-1; j >= 0; j-- ) - { - //Cruise along, find location to insert - if( j > 0 && ( !SoundDrivers[j-1] || SoundDriverPriorities[j-1] < priority ) ) - { - SoundDrivers[j] = SoundDrivers[j-1]; - SoundDriverNames[j] = SoundDriverNames[j-1]; - SoundDriverPriorities[j] = SoundDriverPriorities[j-1]; - } - else - { - SoundDrivers[j] = fn; - SoundDriverNames[j] = strdup( name ); - SoundDriverPriorities[j] = priority; - break; - } - } -} - -struct SoundDriver * InitSound( const char * driver_name, SoundCBType cb ) -{ - int i; - struct SoundDriver * ret = 0; - if( driver_name == 0 || strlen( driver_name ) == 0 ) - { - //Search for a driver. - for( i = 0; i < MAX_SOUND_DRIVERS; i++ ) - { - if( SoundDrivers[i] == 0 ) - { - return 0; - } - ret = SoundDrivers[i]( cb ); - if( ret ) - { - return ret; - } - } - } - else - { - printf( "Initializing sound. Recommended driver: %s\n", driver_name ); - for( i = 0; i < MAX_SOUND_DRIVERS; i++ ) - { - if( SoundDrivers[i] == 0 ) - { - return 0; - } - if( strcmp( SoundDriverNames[i], driver_name ) == 0 ) - { - return SoundDrivers[i]( cb ); - } - } - } - return 0; -} - -int SoundState( struct SoundDriver * soundobject ) -{ - if( soundobject ) - { - return soundobject->SoundStateFn( soundobject ); - } - return -1; -} - -void CloseSound( struct SoundDriver * soundobject ) -{ - if( soundobject ) - { - soundobject->CloseFn( soundobject ); - } -} - diff --git a/colorchord2/sound.h b/colorchord2/sound.h deleted file mode 100644 index 38a7f19..0000000 --- a/colorchord2/sound.h +++ /dev/null @@ -1,41 +0,0 @@ -//Copyright 2015 <>< Charles Lohr under the ColorChord License. - -#ifndef _SOUND_H -#define _SOUND_H - -#define MAX_SOUND_DRIVERS 10 - -struct SoundDriver; - -typedef void(*SoundCBType)( float * out, float * in, int samplesr, int * samplesp, struct SoundDriver * sd ); -typedef void*(SoundInitFn)( SoundCBType cb ); - -struct SoundDriver -{ - void (*CloseFn)( void * object ); - int (*SoundStateFn)( struct SoundDriver * object ); - SoundCBType callback; - int channelsPlay; - int spsPlay; - int channelsRec; - int spsRec; - - //More fields may exist on a per-sound-driver basis -}; - -//Accepts: -// samplerate=44100;channels=2;devplay=default;devrecord=default;record=1;play=1;minavailcount=4096;stopthresh=1024;startthresh=4096;buffer=1024 -// buffer is in samples -//If DriverName = 0 or empty, will try to find best driver. -struct SoundDriver * InitSound( const char * driver_name, SoundCBType cb ); -int SoundState( struct SoundDriver * soundobject ); //returns 0 if okay, negative if faulted. -void CloseSound( struct SoundDriver * soundobject ); - -//Called by various sound drivers. Notice priority must be greater than 0. Priority of 0 or less will not register. -void RegSound( int priority, const char * name, SoundInitFn * fn ); - -#define REGISTER_SOUND( sounddriver, priority, name, function ) \ - void __attribute__((constructor)) REGISTER##sounddriver() { RegSound( priority, name, function ); } - -#endif - diff --git a/colorchord2/sound_alsa.c b/colorchord2/sound_alsa.c deleted file mode 100644 index 3771752..0000000 --- a/colorchord2/sound_alsa.c +++ /dev/null @@ -1,364 +0,0 @@ -//Copyright 2015 <>< Charles Lohr under the ColorChord License. - -#include "sound.h" -#include "os_generic.h" -#include "parameters.h" -#include -#include - -#define BUFFERSETS 4 - -#define BLOCKING - -struct SoundDriverAlsa -{ - void (*CloseFn)( struct SoundDriverAlsa * object ); - int (*SoundStateFn)( struct SoundDriverAlsa * object ); - SoundCBType callback; - int channelsPlay; - int spsPlay; - int channelsRec; - int spsRec; - int alsa_fmt_s16le; - - snd_pcm_uframes_t buffer; - og_thread_t thread; - snd_pcm_t *playback_handle; - snd_pcm_t *record_handle; - - //More fields may exist on a per-sound-driver basis -}; - -static struct SoundDriverAlsa* InitASound( struct SoundDriverAlsa * r ); - -void CloseSoundAlsa( struct SoundDriverAlsa * r ); - -int SoundStateAlsa( struct SoundDriverAlsa * soundobject ) -{ - return ((soundobject->playback_handle)?1:0) | ((soundobject->record_handle)?2:0); -} - -void CloseSoundAlsa( struct SoundDriverAlsa * r ) -{ - if( r ) - { - if( r->playback_handle ) snd_pcm_close (r->playback_handle); - if( r->record_handle ) snd_pcm_close (r->record_handle); -#ifdef BLOCKING - OGUSleep(2000); - OGCancelThread( r->thread ); -#endif - free( r ); - } -} - - -static int SetHWParams( snd_pcm_t * handle, int * samplerate, int * channels, snd_pcm_uframes_t * buffer, struct SoundDriverAlsa * a ) -{ - int err; - snd_pcm_hw_params_t *hw_params; - if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { - fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", - snd_strerror (err)); - return -1; - } - - if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) { - fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", - snd_strerror (err)); - goto fail; - } - - if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { - fprintf (stderr, "cannot set access type (%s)\n", - snd_strerror (err)); - goto fail; - } - - if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_FLOAT )) < 0) { - fprintf (stderr, "cannot set sample format (%s)\n", - snd_strerror (err)); - - printf( "Trying backup: S16LE.\n" ); - if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_S16_LE )) < 0) { - fprintf (stderr, "cannot set sample format (%s)\n", - snd_strerror (err)); - goto fail; - } - - a->alsa_fmt_s16le = 1; - } - - if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, (unsigned int*)samplerate, 0)) < 0) { - fprintf (stderr, "cannot set sample rate (%s)\n", - snd_strerror (err)); - goto fail; - } - - if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, *channels)) < 0) { - fprintf (stderr, "cannot set channel count (%s)\n", - snd_strerror (err)); - goto fail; - } - - int dir = 0; - if( (err = snd_pcm_hw_params_set_period_size_near(handle, hw_params, buffer, &dir)) < 0 ) - { - fprintf( stderr, "cannot set period size. (%s)\n", - snd_strerror(err) ); - goto fail; - } - - - if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) { - fprintf (stderr, "cannot set parameters (%s)\n", - snd_strerror (err)); - goto fail; - } - - snd_pcm_hw_params_free (hw_params); - return 0; -fail: - snd_pcm_hw_params_free (hw_params); - return -2; -} - - -static int SetSWParams( snd_pcm_t * handle, int isrec ) -{ - snd_pcm_sw_params_t *sw_params; - int err; - //Time for software parameters: - - if( !isrec ) - { - if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { - fprintf (stderr, "cannot allocate software parameters structure (%s)\n", - snd_strerror (err)); - goto failhard; - } - if ((err = snd_pcm_sw_params_current (handle, sw_params)) < 0) { - fprintf (stderr, "cannot initialize software parameters structure (%s) (%p)\n", - snd_strerror (err), handle); - goto fail; - } - if ((err = snd_pcm_sw_params_set_avail_min (handle, sw_params, GetParameterI( "minavailcount", 2048 ) )) < 0) { - fprintf (stderr, "cannot set minimum available count (%s)\n", - snd_strerror (err)); - goto fail; - } - if ((err = snd_pcm_sw_params_set_stop_threshold(handle, sw_params, GetParameterI( "stopthresh", 512 ))) < 0) { - fprintf (stderr, "cannot set minimum available count (%s)\n", - snd_strerror (err)); - goto fail; - } - if ((err = snd_pcm_sw_params_set_start_threshold(handle, sw_params, GetParameterI( "startthresh", 2048 ))) < 0) { - fprintf (stderr, "cannot set minimum available count (%s)\n", - snd_strerror (err)); - goto fail; - } - if ((err = snd_pcm_sw_params (handle, sw_params)) < 0) { - fprintf (stderr, "cannot set software parameters (%s)\n", - snd_strerror (err)); - goto fail; - } - - } - - - if ((err = snd_pcm_prepare (handle)) < 0) { - fprintf (stderr, "cannot prepare audio interface for use (%s)\n", - snd_strerror (err)); - goto fail; - } - - - return 0; -fail: - if( !isrec ) - { - snd_pcm_sw_params_free (sw_params); - } -failhard: - return -1; -} - -#ifdef BLOCKING -static void * SoundThread( void * v ) -{ - int i; - struct SoundDriverAlsa * a = (struct SoundDriverAlsa*)v; - float * bufr[BUFFERSETS]; - float * bufp[BUFFERSETS]; - - for(i = 0; i < BUFFERSETS; i++ ) - { - bufr[i] = malloc( a->buffer * sizeof(float) * a->channelsRec ); - bufp[i] = malloc( a->buffer * sizeof(float) * a->channelsPlay ); - } - - while( a->record_handle || a->playback_handle ) - { - int err; - - i = (i+1)%BUFFERSETS; - - if( a->record_handle ) - { - if( (err = snd_pcm_readi (a->record_handle, bufr[i], a->buffer)) != a->buffer) - { - fprintf (stderr, "read from audio interface failed (%s)\n", - snd_strerror (err)); - if( a->record_handle ) snd_pcm_close (a->record_handle); - a->record_handle = 0; - } - else - { - //has_rec = 1; - } - } - - if( a->alsa_fmt_s16le ) - { - //Hacky: Turns out data was s16le. - int16_t * dat = (int16_t*)bufr[i]; - float * dot = bufr[i]; - int i; - int len = a->buffer; - for( i = len-1; i >= 0; i-- ) - { - dot[i] = dat[i]/32768.0; - } - } - //Do our callback. - int playbacksamples = 0; - a->callback( bufp[i], bufr[i], a->buffer, &playbacksamples, (struct SoundDriver*)a ); - //playbacksamples *= sizeof(float) * a->channelsPlay; - - if( a->playback_handle ) - { - if ((err = snd_pcm_writei (a->playback_handle, bufp[i], playbacksamples)) != playbacksamples) - { - fprintf (stderr, "write to audio interface failed (%s)\n", - snd_strerror (err)); - if( a->playback_handle ) snd_pcm_close (a->playback_handle); - a->playback_handle = 0; - } - } - } - - //Fault happened, re-initialize? - InitASound( a ); - return 0; -} -#else - -//Handle callback - -static struct SoundDriverAlsa * reccb; -static int record_callback (snd_pcm_sframes_t nframes) -{ - int err; - -// printf ("playback callback called with %u frames\n", nframes); - - /* ... fill buf with data ... */ - - if ((err = snd_pcm_writei (playback_handle, buf, nframes)) < 0) { - fprintf (stderr, "write failed (%s)\n", snd_strerror (err)); - } - - return err; -} - -#endif - -static struct SoundDriverAlsa * InitASound( struct SoundDriverAlsa * r ) -{ - int err; - if( GetParameterI( "play", 0 ) ) - { - if ((err = snd_pcm_open (&r->playback_handle, GetParameterS( "devplay", "default" ), SND_PCM_STREAM_PLAYBACK, 0)) < 0) { - fprintf (stderr, "cannot open output audio device (%s)\n", - snd_strerror (err)); - goto fail; - } - } - - if( GetParameterI( "record", 1 ) ) - { - if ((err = snd_pcm_open (&r->record_handle, GetParameterS( "devrecord", "default" ), SND_PCM_STREAM_CAPTURE, 0)) < 0) { - fprintf (stderr, "cannot open input audio device (%s)\n", - snd_strerror (err)); - goto fail; - } - } - - - - if( r->playback_handle ) - { - if( SetHWParams( r->playback_handle, &r->spsPlay, &r->channelsPlay, &r->buffer, r ) < 0 ) - goto fail; - if( SetSWParams( r->playback_handle, 0 ) < 0 ) - goto fail; - } - - if( r->record_handle ) - { - if( SetHWParams( r->record_handle, &r->spsRec, &r->channelsRec, &r->buffer, r ) < 0 ) - goto fail; - if( SetSWParams( r->record_handle, 1 ) < 0 ) - goto fail; - } - - if( r->playback_handle && r->record_handle ) - { - snd_pcm_link ( r->playback_handle, r->record_handle ); - } - -#ifdef BLOCKING - r->thread = OGCreateThread( SoundThread, r ); -#else - reccb = r; - //handle interrupt -#endif - return r; - -fail: - if( r ) - { - if( r->playback_handle ) snd_pcm_close (r->playback_handle); - if( r->record_handle ) snd_pcm_close (r->record_handle); - free( r ); - } - return 0; -} - - - -void * InitSoundAlsa( SoundCBType cb ) -{ - struct SoundDriverAlsa * r = malloc( sizeof( struct SoundDriverAlsa ) ); - - r->CloseFn = CloseSoundAlsa; - r->SoundStateFn = SoundStateAlsa; - r->callback = cb; - - r->spsPlay = GetParameterI( "samplerate", 44100 ); - r->channelsPlay = GetParameterI( "channels", 2 ); - r->spsRec = r->spsPlay; - r->channelsRec = r->channelsPlay; - - r->playback_handle = 0; - r->record_handle = 0; - r->buffer = GetParameterI( "buffer", 1024 ); - - r->alsa_fmt_s16le = 0; - - - return InitASound(r); -} - -REGISTER_SOUND( AlsaSound, 10, "ALSA", InitSoundAlsa ); - diff --git a/colorchord2/sound_android.c b/colorchord2/sound_android.c deleted file mode 100644 index 6975802..0000000 --- a/colorchord2/sound_android.c +++ /dev/null @@ -1,244 +0,0 @@ -//Copyright 2019-2020 <>< Charles Lohr under the ColorChord License. -// This should be used with rawdrawandroid - -#include "sound.h" -#include "os_generic.h" -#include //Using android threads not os_generic threads. -#include -#include -#include -#include - -#ifndef NO_SOUND_PARAMETERS -#include "parameters.h" -#else -#define GetParameterI( x, y ) (y) -#define GetParameterS( x, y ) (y) -#endif - - -//based on https://github.com/android/ndk-samples/blob/master/native-audio/app/src/main/cpp/native-audio-jni.c - -// for native audio -#include -#include - -#include -#include -#include -#include - -#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APPNAME, __VA_ARGS__)) -#define printf( x...) LOGI( x ) - -#define RECORDER_FRAMES 1024 - -#define BUFFERSETS 4 - -#define BLOCKING - -//Across all sound systems. -static pthread_mutex_t audioEngineLock = PTHREAD_MUTEX_INITIALIZER; - -struct SoundDriverAndroid -{ - void (*CloseFn)( struct SoundDriverAndroid * object ); - int (*SoundStateFn)( struct SoundDriverAndroid * object ); - SoundCBType callback; - SLObjectItf engineObject; - SLEngineItf engineEngine; - SLRecordItf recorderRecord; - SLObjectItf recorderObject; - SLAndroidSimpleBufferQueueItf recorderBufferQueue; - unsigned recorderSize; - - short recorderBuffer[RECORDER_FRAMES]; -}; - - -void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) -{ - struct SoundDriverAndroid * r = (struct SoundDriverAndroid*)context; - int samplesp = 0; - float buffout[RECORDER_FRAMES]; - int i; - short * rb = r->recorderBuffer; - for( i = 0; i < RECORDER_FRAMES; i++ ) buffout[i] = (rb[i]+0.5)/32767.5; - r->callback( 0, buffout, RECORDER_FRAMES, &samplesp, r ); - (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer)); -} - -static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * r ) -{ - SLresult result; - LOGI( "Starting InitAndroidSound\n" ); - // create engine - result = slCreateEngine(&r->engineObject, 0, NULL, 0, NULL, NULL); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - // realize the engine - result = (*r->engineObject)->Realize(r->engineObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - // get the engine interface, which is needed in order to create other objects - result = (*r->engineObject)->GetInterface(r->engineObject, SL_IID_ENGINE, &r->engineEngine); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - - /////////////////////////////////////////////////////////////////////////////////////////////////////// - - - // configure audio source - SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, - SL_DEFAULTDEVICEID_AUDIOINPUT, NULL}; - SLDataSource audioSrc = {&loc_dev, NULL}; - - // configure audio sink - SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; - - SLDataFormat_PCM format_pcm ={ - SL_DATAFORMAT_PCM, - 1, - SL_SAMPLINGRATE_16, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_SPEAKER_FRONT_CENTER, - SL_BYTEORDER_LITTLEENDIAN, - }; - - SLDataSink audioSnk = {&loc_bq, &format_pcm}; - - // create audio recorder - // (requires the RECORD_AUDIO permission) - const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; - const SLboolean req[1] = {SL_BOOLEAN_TRUE}; - result = (*r->engineEngine)->CreateAudioRecorder(r->engineEngine, &r->recorderObject, &audioSrc, - &audioSnk, 1, id, req); - if (SL_RESULT_SUCCESS != result) { - LOGI( "CreateAudioRecorder failed\n" ); - return JNI_FALSE; - } - - // realize the audio recorder - result = (*r->recorderObject)->Realize(r->recorderObject, SL_BOOLEAN_FALSE); - if (SL_RESULT_SUCCESS != result) { - LOGI( "AudioRecorder Realize failed: %d\n", result ); - return JNI_FALSE; - } - - // get the record interface - result = (*r->recorderObject)->GetInterface(r->recorderObject, SL_IID_RECORD, &r->recorderRecord); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - // get the buffer queue interface - result = (*r->recorderObject)->GetInterface(r->recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, - &r->recorderBufferQueue); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - // register callback on the buffer queue - result = (*r->recorderBufferQueue)->RegisterCallback(r->recorderBufferQueue, bqRecorderCallback, r); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - - assert( !pthread_mutex_trylock(&audioEngineLock)); - // in case already recording, stop recording and clear buffer queue - result = (*r->recorderRecord)->SetRecordState(r->recorderRecord, SL_RECORDSTATE_STOPPED); - assert(SL_RESULT_SUCCESS == result); - (void)result; - result = (*r->recorderBufferQueue)->Clear(r->recorderBufferQueue); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - // the buffer is not valid for playback yet - r->recorderSize = 0; - - // enqueue an empty buffer to be filled by the recorder - // (for streaming recording, we would enqueue at least 2 empty buffers to start things off) - result = (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer)); - // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, - // which for this code example would indicate a programming error - assert(SL_RESULT_SUCCESS == result); - (void)result; - - // start recording - result = (*r->recorderRecord)->SetRecordState(r->recorderRecord, SL_RECORDSTATE_RECORDING); - assert(SL_RESULT_SUCCESS == result); - (void)result; - - LOGI( "Complete Init Sound Android\n" ); - return r; -} - -void CloseSoundAndroid( struct SoundDriverAndroid * r ); - -int SoundStateAndroid( struct SoundDriverAndroid * soundobject ) -{ - return ((soundobject->recorderObject)?1:0) | ((soundobject->recorderObject)?2:0); -} - -void CloseSoundAndroid( struct SoundDriverAndroid * r ) -{ - // destroy audio recorder object, and invalidate all associated interfaces - if (r->recorderObject != NULL) { - (*r->recorderObject)->Destroy(r->recorderObject); - r->recorderObject = NULL; - r->recorderRecord = NULL; - r->recorderBufferQueue = NULL; - } - - - // destroy engine object, and invalidate all associated interfaces - if (r->engineObject != NULL) { - (*r->engineObject)->Destroy(r->engineObject); - r->engineObject = NULL; - r->engineEngine = NULL; - } - -} - - -int AndroidHasPermissions(const char* perm_name); -void AndroidRequestAppPermissions(const char * perm); - - -void * InitSoundAndroid( SoundCBType cb ) -{ - int hasperm = AndroidHasPermissions( "RECORD_AUDIO" ); - if( !hasperm ) - { - AndroidRequestAppPermissions( "RECORD_AUDIO" ); - } - - struct SoundDriverAndroid * r = (struct SoundDriverAndroid *)malloc( sizeof( struct SoundDriverAndroid ) ); - memset( r, 0, sizeof( *r) ); - r->CloseFn = CloseSoundAndroid; - r->SoundStateFn = SoundStateAndroid; - r->callback = cb; - r->engineObject = 0; - r->engineEngine = 0; -/* - r->spsPlay = GetParameterI( "samplerate", 44100 ); - r->channelsPlay = GetParameterI( "channels", 2 ); - r->spsRec = r->spsPlay; - r->channelsRec = r->channelsPlay; - - r->playback_handle = 0; - r->record_handle = 0; - r->buffer = GetParameterI( "buffer", 1024 ); - - r->Android_fmt_s16le = 0; - -*/ - return InitAndroidSound(r); -} - -//Tricky: On Android, this can't actually run before main. Have to manually execute it. - -REGISTER_SOUND( AndroidSound, 10, "ANDROID", InitSoundAndroid ); - diff --git a/colorchord2/sound_null.c b/colorchord2/sound_null.c deleted file mode 100644 index d7f8d16..0000000 --- a/colorchord2/sound_null.c +++ /dev/null @@ -1,45 +0,0 @@ -//Copyright 2015 <>< Charles Lohr under the ColorChord License. - -#include "sound.h" -#include "os_generic.h" -#include -#include "parameters.h" - -struct SoundDriverNull -{ - void (*CloseFn)( struct SoundDriverNull * object ); - int (*SoundStateFn)( struct SoundDriverNull * object ); - SoundCBType soundcb; - int channelsPlay; - int spsPlay; - int channelsRec; - int spsRec; -}; - -void CloseSoundNull( struct SoundDriverNull * object ) -{ - free( object ); -} - -int SoundStateNull( struct SoundDriverNull * object ) -{ - return 0; -} - - -void * InitSoundNull( SoundCBType cb ) -{ - struct SoundDriverNull * r = malloc( sizeof( struct SoundDriverNull ) ); - r->CloseFn = CloseSoundNull; - r->SoundStateFn = SoundStateNull; - r->soundcb = cb; - r->spsPlay = GetParameterI( "samplerate", 44100 ); - r->channelsPlay = GetParameterI( "channels", 2 ); - r->spsRec = r->spsPlay; - r->channelsRec = r->channelsRec; - return r; -} - - -REGISTER_SOUND( NullSound, 1, "NULL", InitSoundNull ); - diff --git a/colorchord2/sound_pulse.c b/colorchord2/sound_pulse.c deleted file mode 100644 index 4664c2e..0000000 --- a/colorchord2/sound_pulse.c +++ /dev/null @@ -1,379 +0,0 @@ -//Copyright 2015 <>< Charles Lohr under the ColorChord License. - -//This file is really rough. Full duplex doesn't seem to work hardly at all. - - -#include "sound.h" -#include "os_generic.h" -#include "parameters.h" -#include - -#include -#include -#include -#include -#include - -#define BUFFERSETS 3 - - -//from http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/Clients/Samples/AsyncPlayback/ -//also http://maemo.org/api_refs/5.0/5.0-final/pulseaudio/pacat_8c-example.html - - -struct SoundDriverPulse -{ - void (*CloseFn)( struct SoundDriverPulse * object ); - int (*SoundStateFn)( struct SoundDriverPulse * object ); - SoundCBType callback; - int channelsPlay; - int spsPlay; - int channelsRec; - int spsRec; - - const char * sourceName; - og_thread_t thread; - pa_stream * play; - pa_stream * rec; - pa_context * pa_ctx; - pa_mainloop *pa_ml; - int pa_ready; - int buffer; - //More fields may exist on a per-sound-driver basis -}; - - - -void CloseSoundPulse( struct SoundDriverPulse * r ); - -int SoundStatePulse( struct SoundDriverPulse * soundobject ) -{ - return ((soundobject->play)?1:0) | ((soundobject->rec)?2:0); -} - -void CloseSoundPulse( struct SoundDriverPulse * r ) -{ - if( r ) - { - if( r->play ) - { - pa_stream_unref (r->play); - r->play = 0; - } - - if( r->rec ) - { - pa_stream_unref (r->rec); - r->rec = 0; - } - OGUSleep(2000); - OGCancelThread( r->thread ); - free( r ); - } -} - -static void * SoundThread( void * v ) -{ - struct SoundDriverPulse * r = (struct SoundDriverPulse*)v; - while(1) - { - pa_mainloop_iterate( r->pa_ml, 1, NULL ); - } - return 0; -} -/* - int i; - int error; - struct SoundDriverPulse * r = (struct SoundDriverPulse*)v; - - float * bufr[BUFFERSETS]; - float * bufp[BUFFERSETS]; - - for(i = 0; i < BUFFERSETS; i++ ) - { - bufr[i] = malloc( r->buffer * sizeof(float) * r->channelsRec ); - bufp[i] = malloc( r->buffer * sizeof(float) * r->channelsPlay ); - } - - while( r->play || r->rec ) - { - i = (i+1)%BUFFERSETS; - - if( r->rec ) - { - if (pa_stream_read(r->rec, bufr[i], r->buffer * sizeof(float) * r->channelsRec, &error) < 0) { - fprintf(stderr, __FILE__": pa_stream_write() failed: %s\n", pa_strerror(error)); - pa_stream_unref( r->play ); - r->rec = 0; - } - } - - int playbacksamples = 0; - r->callback( bufp[i], bufr[i], r->buffer, &playbacksamples, (struct SoundDriver*)r ); - playbacksamples *= sizeof( float ) * r->channelsPlay; - - if( r->play ) - { - if (pa_stream_write(r->play, bufp[i], playbacksamples, NULL, 0LL, PA_SEEK_RELATIVE) < 0) { - fprintf(stderr, __FILE__": pa_stream_write() failed: %s\n", pa_strerror(error)); - pa_stream_unref( r->play ); - r->play = 0; - } - } - } - -}*/ - -static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { -// pa_usec_t usec; - - struct SoundDriverPulse * r = (struct SoundDriverPulse*)userdata; - if( r->rec ) - { - return; - } - -/* - //Neat: You might want this: - - pa_stream_get_latency(s,&usec,&neg); - - if (sampleoffs*2 + length > sizeof(sampledata)) - { - sampleoffs = 0; - } - - if (length > sizeof(sampledata)) { - length = sizeof(sampledata); - } - -*/ - - -// pa_stream_write(s, &sampledata[sampleoffs], length, NULL, 0LL, PA_SEEK_RELATIVE); - int playbacksamples = 0; - float bufr[r->buffer*r->channelsRec]; - float bufp[r->buffer*r->channelsPlay]; - - r->callback( bufp, bufr, r->buffer, &playbacksamples, (struct SoundDriver*)r ); - //playbacksamples *= sizeof( float ) * r->channelsPlay; - - pa_stream_write(r->play, &bufp, playbacksamples, NULL, 0LL, PA_SEEK_RELATIVE); - -} - - -static void stream_record_cb(pa_stream *s, size_t length, void *userdata) { -// pa_usec_t usec; -// int neg; - - struct SoundDriverPulse * r = (struct SoundDriverPulse*)userdata; - -/* pa_stream_get_latency(s,&usec,&neg); - printf(" latency %8d us\n",(int)usec); - - if (sampleoffs*2 + length > sizeof(sampledata)) - { - sampleoffs = 0; - } - - if (length > sizeof(sampledata)) { - length = sizeof(sampledata); - }*/ - - int playbacksamples = 0; - float * bufr; - - if (pa_stream_peek(r->rec, (void*)&bufr, &length) < 0) { - fprintf(stderr, ("pa_stream_peek() failed: %s\n"), pa_strerror(pa_context_errno(r->pa_ctx))); - return; - } - - float * buffer; - buffer = pa_xmalloc(length); - memcpy(buffer, bufr, length); - pa_stream_drop(r->rec); - - float bufp[length*r->channelsPlay]; - r->callback( bufp, buffer, length/sizeof(float)/r->channelsRec, &playbacksamples, (struct SoundDriver*)r ); - //playbacksamples *= sizeof( float ) * r->channelsPlay; - pa_xfree( buffer ); - if( r->play ) - pa_stream_write(r->play, &bufp, playbacksamples*sizeof(float)*r->channelsPlay, NULL, 0LL, PA_SEEK_RELATIVE); -} - - - -static void stream_underflow_cb(pa_stream *s, void *userdata) { - // We increase the latency by 50% if we get 6 underflows and latency is under 2s - // This is very useful for over the network playback that can't handle low latencies - printf("underflow\n"); -// underflows++; -/* if (underflows >= 6 && latency < 2000000) { - latency = (latency*3)/2; - bufattr.maxlength = pa_usec_to_bytes(latency,&ss); - bufattr.tlength = pa_usec_to_bytes(latency,&ss); - pa_stream_set_buffer_attr(s, &bufattr, NULL, NULL); - underflows = 0; - printf("latency increased to %d\n", latency); - }*/ -} - - -void pa_state_cb(pa_context *c, void *userdata) { - pa_context_state_t state; - int *pa_ready = userdata; - state = pa_context_get_state(c); - switch (state) { - // These are just here for reference - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - default: - break; - case PA_CONTEXT_FAILED: - case PA_CONTEXT_TERMINATED: - *pa_ready = 2; - break; - case PA_CONTEXT_READY: - *pa_ready = 1; - break; - } -} - - -void * InitSoundPulse( SoundCBType cb ) -{ - static pa_buffer_attr bufattr; - static pa_sample_spec ss; - int error; - pa_mainloop_api *pa_mlapi; - struct SoundDriverPulse * r = malloc( sizeof( struct SoundDriverPulse ) ); - - r->pa_ml = pa_mainloop_new(); - pa_mlapi = pa_mainloop_get_api(r->pa_ml); - const char * title = GetParameterS( "title", "PA Test" ); - r->pa_ctx = pa_context_new(pa_mlapi, title ); - pa_context_connect(r->pa_ctx, NULL, 0, NULL); - - //TODO: pa_context_set_state_callback - - r->CloseFn = CloseSoundPulse; - r->SoundStateFn = SoundStatePulse; - r->callback = cb; - - r->spsPlay = GetParameterI( "samplerate", 44100 ); - r->channelsPlay = GetParameterI( "channels", 2 ); - r->spsRec = r->spsPlay; - r->channelsRec = r->channelsPlay; - r->sourceName = GetParameterS( "sourcename", NULL ); - - if( strcmp( r->sourceName, "default" ) == 0 ) - { - r->sourceName = 0; - } - - r->play = 0; - r->rec = 0; - r->buffer = GetParameterI( "buffer", 1024 ); - printf ("Pulse: from: %s (%s) / %dx%d (%d)\n", r->sourceName, title, r->spsPlay, r->channelsPlay, r->buffer ); - - memset( &ss, 0, sizeof( ss ) ); - - ss.format = PA_SAMPLE_FLOAT32NE; - ss.rate = r->spsPlay; - ss.channels = r->channelsPlay; - - r->pa_ready = 0; - pa_context_set_state_callback(r->pa_ctx, pa_state_cb, &r->pa_ready); - - while (r->pa_ready == 0) - { - pa_mainloop_iterate(r->pa_ml, 1, NULL); - } - - int bufbytes = r->buffer * sizeof(float) * r->channelsRec; - - if( GetParameterI( "play", 1 ) ) - { - if (!(r->play = pa_stream_new(r->pa_ctx, "Play", &ss, NULL))) { - error = -3; //XXX ??? TODO - fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); - goto fail; - } - - pa_stream_set_underflow_callback(r->play, stream_underflow_cb, NULL); - pa_stream_set_write_callback(r->play, stream_request_cb, r ); - - bufattr.fragsize = (uint32_t)-1; - bufattr.maxlength = bufbytes*3; //XXX TODO Consider making this -1 - bufattr.minreq = 0; - bufattr.prebuf = (uint32_t)-1; - bufattr.tlength = bufbytes*3; - int ret = pa_stream_connect_playback(r->play, NULL, &bufattr, - // PA_STREAM_INTERPOLATE_TIMING - // |PA_STREAM_ADJUST_LATENCY //Some servers don't like the adjust_latency flag. - // |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); - 0, NULL, NULL ); - printf( "Play stream.\n" ); - if( ret < 0 ) - { - fprintf(stderr, __FILE__": (PLAY) pa_stream_connect_playback() failed: %s\n", pa_strerror(ret)); - goto fail; - } - } - - if( GetParameterI( "rec", 1 ) ) - { - if (!(r->rec = pa_stream_new(r->pa_ctx, "Record", &ss, NULL))) { - error = -3; //XXX ??? TODO - fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); - goto fail; - } - - pa_stream_set_read_callback(r->rec, stream_record_cb, r ); - - bufattr.fragsize = bufbytes; - bufattr.maxlength = (uint32_t)-1;//(uint32_t)-1; //XXX: Todo, should this be low? - bufattr.minreq = bufbytes; - bufattr.prebuf = (uint32_t)-1; - bufattr.tlength = bufbytes*3; - printf( "Source: %s\n", r->sourceName ); - int ret = pa_stream_connect_record(r->rec, r->sourceName, &bufattr, 0 -// |PA_STREAM_INTERPOLATE_TIMING - |PA_STREAM_ADJUST_LATENCY //Some servers don't like the adjust_latency flag. -// |PA_STREAM_AUTO_TIMING_UPDATE -// 0 - ); - - printf( "Got handle: %d\n", ret ); - if( ret < 0 ) - { - fprintf(stderr, __FILE__": (REC) pa_stream_connect_playback() failed: %s\n", pa_strerror(ret)); - goto fail; - } - } - - printf( "Pulse initialized.\n" ); - - -// SoundThread( r ); - r->thread = OGCreateThread( SoundThread, r ); - return r; - -fail: - if( r ) - { - if( r->play ) pa_xfree (r->play); - if( r->rec ) pa_xfree (r->rec); - free( r ); - } - return 0; -} - - - -REGISTER_SOUND( PulseSound, 11, "PULSE", InitSoundPulse ); - - diff --git a/colorchord2/sound_win.c b/colorchord2/sound_win.c deleted file mode 100644 index da41efc..0000000 --- a/colorchord2/sound_win.c +++ /dev/null @@ -1,190 +0,0 @@ -//Copyright 2015 <>< Charles Lohr under the ColorChord License. - -#include -#include "parameters.h" -#include "sound.h" -#include "os_generic.h" -#include -#include -#include -#include - -#if defined(WIN32) && !defined( TCC ) -#pragma comment(lib,"winmm.lib") -#endif - -#define BUFFS 2 - -struct SoundDriverWin -{ - void (*CloseFn)( struct SoundDriverWin * object ); - int (*SoundStateFn)( struct SoundDriverWin * object ); - SoundCBType callback; - int channelsPlay; - int spsPlay; - int channelsRec; - int spsRec; - - - int buffer; - int isEnding; - int GOBUFF; - - int recording; - - HWAVEIN hMyWave; - WAVEHDR WavBuff[BUFFS]; -}; - -static struct SoundDriverWin * w; - -void CloseSoundWin( struct SoundDriverWin * r ) -{ - int i; - - if( r ) - { - waveInStop(r->hMyWave); - waveInReset(r->hMyWave); - - for ( i=0;ihMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR)); - free ((r->WavBuff[i]).lpData); - } - waveInClose(r->hMyWave); - free( r ); - } -} - -int SoundStateWin( struct SoundDriverWin * soundobject ) -{ - return soundobject->recording; -} - -void CALLBACK HANDLEMIC(HWAVEIN hwi,UINT umsg, DWORD dwi, DWORD hdr, DWORD dwparm) -{ - int ctr; - int ob; - long cValue; - unsigned int maxWave=0; - - float buffer[w->buffer*w->channelsRec]; - - if (w->isEnding) return; - - switch (umsg) - { - case MM_WIM_OPEN: - printf( "Mic Open.\n" ); - w->recording = 1; - break; - - case MM_WIM_DATA: -// printf( "Mic Data.\n"); - ob = (w->GOBUFF+(BUFFS))%BUFFS; -// waveInPrepareHeader(w->hMyWave,&(w->WavBuff[w->Cbuff]),sizeof(WAVEHDR)); - - for (ctr=0;ctrbuffer * w->channelsRec;ctr++) { - float cv = (uint16_t)(((uint8_t)w->WavBuff[ob].lpData[ctr*2+1])*256+((uint8_t)w->WavBuff[ob].lpData[ctr*2])+32768)-32768; - cv /= 32768; -// if( ctr < 3 ) cv = -1; -// buffer[(w->buffer * w->channelsRec)-ctr-1] = cv; - buffer[ctr] = cv; - } - - waveInAddBuffer(w->hMyWave,&(w->WavBuff[w->GOBUFF]),sizeof(WAVEHDR)); - w->GOBUFF = ( w->GOBUFF + 1 ) % BUFFS; - - int playbacksamples; //Unused - w->callback( 0, buffer, w->buffer, &playbacksamples, (struct SoundDriver*)w ); - - } -} - - -static struct SoundDriverWin * InitWinSound( struct SoundDriverWin * r ) -{ - int i; - WAVEFORMATEX wfmt; - memset( &wfmt, 0, sizeof(wfmt) ); - printf ("WFMT Size (debugging temp for TCC): %d\n", sizeof(wfmt) ); - if( GetParameterI( "play", 0 ) ) - { - fprintf( stderr, "Error: This Windows Sound Driver does not support playback.\n" ); - exit( -1 ); - } - - w = r; - - - printf( "WFMT: %d %d %d\n", r->channelsRec, r->spsRec, - r->spsRec * r->channelsRec ); - - wfmt.wFormatTag = WAVE_FORMAT_PCM; - wfmt.nChannels = r->channelsRec; - wfmt.nSamplesPerSec = r->spsRec; - wfmt.nAvgBytesPerSec = r->spsRec * r->channelsRec; - wfmt.nBlockAlign = r->channelsRec * 2; - wfmt.wBitsPerSample = 16; - wfmt.cbSize = 0; - - long dwdevice; - dwdevice = GetParameterI( "wininput", WAVE_MAPPER ); - - printf( "Wave Devs: %d; WAVE_MAPPER: %d; Selected Input: %d\n", waveInGetNumDevs(), WAVE_MAPPER, dwdevice ); - - printf( "waveInOpen: %p, %p\n", r->hMyWave, &wfmt ); - - int p = waveInOpen(&r->hMyWave, dwdevice, &wfmt, (void*)(&HANDLEMIC) , 0, CALLBACK_FUNCTION); - - if( p ) - { - fprintf( stderr, "Error performing waveInOpen. Received code: %d\n", p ); - } - - for ( i=0;iWavBuff[i]), 0, sizeof(r->WavBuff[i]) ); - (r->WavBuff[i]).dwBufferLength = r->buffer*2*r->channelsRec; - (r->WavBuff[i]).dwLoops = 1; - (r->WavBuff[i]).lpData=(char*) malloc(r->buffer*r->channelsRec*2); - p = waveInPrepareHeader(r->hMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR)); - printf( "WIP: %d\n", p ); - waveInAddBuffer(r->hMyWave,&(r->WavBuff[i]),sizeof(WAVEHDR)); - printf( "WIA: %d\n", p ); - } -\ - p = waveInStart(r->hMyWave); - if( p ) - { - fprintf( stderr, "Error performing waveInStart. Received code %d\n", p ); - } - - return r; -} - - - -void * InitSoundWin( SoundCBType cb ) -{ - struct SoundDriverWin * r = (struct SoundDriverWin *)malloc( sizeof( struct SoundDriverWin ) ); - - r->CloseFn = CloseSoundWin; - r->SoundStateFn = SoundStateWin; - r->callback = cb; - - r->spsRec = GetParameterI( "samplerate", 44100 ); - r->channelsRec = GetParameterI( "channels", 2 ); - r->buffer = GetParameterI( "buffer", 384 ); - r->recording = 0; - r->isEnding = 0; - printf( "Buffer: %d\n", r->buffer ); - - r->GOBUFF=0; - - return InitWinSound(r); -} - -REGISTER_SOUND( SoundWin, 10, "WIN", InitSoundWin ); -