diff options
author | James <james@mackie.(none)> | 2007-06-28 19:50:38 (GMT) |
---|---|---|
committer | James <james@mackie.(none)> | 2007-06-28 19:50:38 (GMT) |
commit | 95307822c2634e4b97c20b8d183340778f6d54a9 (patch) | |
tree | a906b1a01e335e1ded015d049e45bd823f3e6607 /Util/Clooper | |
parent | 25cdff4c6adb135dfdaa020d8f04c24a44d34998 (diff) |
prog
Diffstat (limited to 'Util/Clooper')
-rw-r--r-- | Util/Clooper/aclient.cpp | 208 | ||||
-rw-r--r-- | Util/Clooper/audio.cpp | 219 | ||||
-rw-r--r-- | Util/Clooper/log.cpp | 12 |
3 files changed, 243 insertions, 196 deletions
diff --git a/Util/Clooper/aclient.cpp b/Util/Clooper/aclient.cpp index 52edaa2..f6d39a7 100644 --- a/Util/Clooper/aclient.cpp +++ b/Util/Clooper/aclient.cpp @@ -14,6 +14,16 @@ #include <csound/csound.h> #include <alsa/asoundlib.h> +static double pytime(const struct timeval * tv) +{ + struct timeval t; + if (!tv) + { + tv = &t; + gettimeofday(&t, NULL); + } + return (double) tv->tv_sec + (double) tv->tv_usec / 1000000.0; +} #include "log.cpp" #include "audio.cpp" @@ -26,16 +36,6 @@ int VERBOSE = 3; FILE * _debug = NULL; -static double pytime(const struct timeval * tv) -{ - struct timeval t; - if (!tv) - { - tv = &t; - gettimeofday(&t, NULL); - } - return (double) tv->tv_sec + (double) tv->tv_usec / 1000000.0; -} struct ev_t { @@ -121,187 +121,6 @@ struct ev_t csoundScoreEvent(csound, type, ¶m[0], param.size()); } }; -struct SystemStuff -{ - static void setscheduler(void) - { - struct sched_param sched_param; - - if (sched_getparam(0, &sched_param) < 0) { - printf("Scheduler getparam failed...\n"); - return; - } - sched_param.sched_priority = sched_get_priority_max(SCHED_RR); - - if (sched_setscheduler(0, SCHED_RR, &sched_param)) - { - if (_debug && (VERBOSE > 2)) printf("WARNING: Scheduler set to Round Robin with priority %i failed!\n", sched_param.sched_priority); - } - else - { - if (_debug && (VERBOSE > 2)) printf("INFO: Scheduler set to Round Robin with priority %i.\n", sched_param.sched_priority); - } - } - - /** the currently opened pcm hande */ - snd_pcm_t * pcm; - snd_pcm_uframes_t period_size; - unsigned int rate; - - SystemStuff() : pcm(NULL), period_size(0), rate(0) - { - } - ~SystemStuff() - { - if (pcm) close(0); - } - - int open(unsigned int rate0, int upsample_max, snd_pcm_uframes_t period0, unsigned int p_per_buff) - { - snd_pcm_hw_params_t *hw; - - if (pcm) - { - IF_DEBUG(0) fprintf(_debug, "ERROR: open called twice! First close the sound device\n"); - return -1; - } - - if ( 0 > snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0)) { ERROR_HERE; return -1; } - if ( 0 > snd_pcm_hw_params_malloc(&hw)) { ERROR_HERE; snd_pcm_close(pcm); pcm = NULL; return -1; } - - //now we can be a bit flexible with the buffer size and the sample-rate... - - int upsample; - for (upsample = 1; upsample < upsample_max; ++upsample) - { - rate = rate0 * upsample; - - if ( 0 > snd_pcm_hw_params_any(pcm, hw)) { ERROR_HERE; goto open_error;} - - //first do the compulsory steps... interleaved float, 2 channel - if ( 0 > snd_pcm_hw_params_set_rate_resample(pcm, hw, 0)) { ERROR_HERE; goto open_error;} - if ( 0 > snd_pcm_hw_params_test_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;} - if ( 0 > snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;} - if ( 0 > snd_pcm_hw_params_test_format(pcm, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;} - if ( 0 > snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;} - if ( 0 > snd_pcm_hw_params_set_channels(pcm, hw, 2)) { ERROR_HERE; goto open_error;} - - IF_DEBUG(1) fprintf(_debug, "testing rate : %i\t", rate); - if ( snd_pcm_hw_params_test_rate(pcm, hw, rate, 0)) - { - fprintf(_debug, "failed.\n"); - continue; - } - else - { - IF_DEBUG(1) fprintf(_debug, "success! setting rate : %i\n", rate); - if (0 > snd_pcm_hw_params_set_rate(pcm, hw, rate, 0)) { ERROR_HERE; goto open_error;} - - snd_pcm_uframes_t minb=0, maxb= 0; - int mind=0, maxd=0; - snd_pcm_hw_params_get_period_size_min(hw, &minb,&mind); - snd_pcm_hw_params_get_period_size_max(hw, &maxb,&maxd); - IF_DEBUG(1) fprintf(_debug, "FYI: period size range is [%li/%i,%li/%i]\n", minb,mind, maxb, maxd); - - assert(mind == 0); //rate_resample 0 makes this true right? - assert(maxd == 0); //rate_resample 0 makes this true right? - - if (period0 < minb) - { - IF_DEBUG(1) fprintf(_debug, "requested period size (%li) < min (%li), adjusting to min\n", period_size, minb); - period_size = minb; - } - else if (period0 > maxb) - { - IF_DEBUG(1) fprintf(_debug, "requested period size (%li) < max (%li), adjusting to min\n", period_size, maxb); - period_size = maxb; - } - else - { - period_size = period0; - } - - IF_DEBUG(1) fprintf(_debug, "testing period size : %li\n", period_size); - if ( 0 > snd_pcm_hw_params_test_period_size(pcm, hw, period_size, 0)){ ERROR_HERE; goto open_error;} - - - IF_DEBUG(1) fprintf(_debug, "setting period size : %li\n", period_size); - if ( 0 > snd_pcm_hw_params_set_period_size(pcm, hw, period_size, 0)){ ERROR_HERE; goto open_error;} - - IF_DEBUG(1) fprintf(_debug, "setting buffer size : %i * %li = %li\n", p_per_buff, period_size, p_per_buff * period_size); - if ( 0 > snd_pcm_hw_params_set_buffer_size(pcm, hw, p_per_buff*period_size)) { ERROR_HERE; goto open_error;} - - break; - } - } - - if (upsample_max == upsample) { ERROR_HERE; goto open_error; } - - if (0 > snd_pcm_hw_params(pcm, hw)) { ERROR_HERE; goto open_error; } - - snd_pcm_hw_params_free (hw); - return 0; - -open_error: - snd_pcm_hw_params_free (hw); - snd_pcm_close(pcm); - pcm = NULL; - return -1; - } - void close(int drain = 0) - { - if (!pcm) - { - IF_DEBUG(2) fprintf(_debug, "WARNING: attempt to close already-closed pcm\n"); - return; - } - IF_DEBUG(1) fprintf(_debug, "INFO: closing pcm device\n"); - if (drain) snd_pcm_drain(pcm); - snd_pcm_close(pcm); - pcm = NULL; - } - void prepare() - { - if (!pcm) - { - IF_DEBUG(0) fprintf(_debug, "ERROR: attempt to prepare a closed pcm\n"); - return; - } - if (0 > snd_pcm_prepare(pcm)) { ERROR_HERE; } - } - int writebuf(snd_pcm_uframes_t frame_count, float * frame_data) - { - if (!pcm) - { - IF_DEBUG(0) fprintf(_debug, "ERROR: attempt to write a closed pcm\n"); - return -1; - } - int err; - err = snd_pcm_writei (pcm, frame_data, frame_count ); - if (err == (signed)frame_count) return 0; //success - - assert(err < 0); - - const char * msg = NULL; - snd_pcm_state_t state = snd_pcm_state(pcm); - switch (state) - { - case SND_PCM_STATE_OPEN: msg = "open"; break; - case SND_PCM_STATE_SETUP: msg = "setup"; break; - case SND_PCM_STATE_PREPARED:msg = "prepared"; break; - case SND_PCM_STATE_RUNNING: msg = "running"; break; - case SND_PCM_STATE_XRUN: msg = "xrun"; break; - case SND_PCM_STATE_DRAINING: msg = "draining"; break; - case SND_PCM_STATE_PAUSED: msg = "paused"; break; - case SND_PCM_STATE_SUSPENDED: msg = "suspended"; break; - case SND_PCM_STATE_DISCONNECTED: msg = "disconnected"; break; - } - if (_debug && (VERBOSE > 1)) fprintf (_debug, "WARNING: write failed (%s)\tstate = %s\ttime=%lf\n", snd_strerror (err), msg, pytime(NULL)); - if (0 > snd_pcm_recover(pcm, err, 0)) { ERROR_HERE; return err;} - if (0 > snd_pcm_prepare(pcm)) { ERROR_HERE; return err;} - return 1; //warning - } -}; struct TamTamSound { /** the id of an running sound-rendering thread, or NULL */ @@ -542,11 +361,7 @@ struct TamTamSound period_per_buffer(ppb), up_ratio(0), ll( new log_t(_debug, VERBOSE) ), -#if NEWAUDIO sys_stuff(NULL) -#else - sys_stuff(new SystemStuff()) -#endif { #if NEWAUDIO sys_stuff = new AlsaStuff( "default", "default", SND_PCM_FORMAT_FLOAT, 2, csound_frame_rate, period0, 4, ll); @@ -558,6 +373,7 @@ struct TamTamSound delete sys_stuff; sys_stuff=NULL; #else + sys_stuff = new SystemStuff(ll); if (0 > sys_stuff->open(csound_frame_rate, 4, period0, period_per_buffer)) { return; @@ -654,7 +470,7 @@ struct TamTamSound if (0 > sys_stuff->writebuf(csound_nframes,csoundGetOutputBuffer(csound))) break; #endif } - else + else //fill one period of audio buffer data by 0 or more calls to csound { up_pos = 0; int messed = 0; diff --git a/Util/Clooper/audio.cpp b/Util/Clooper/audio.cpp index e55cc23..0ee6620 100644 --- a/Util/Clooper/audio.cpp +++ b/Util/Clooper/audio.cpp @@ -36,6 +36,225 @@ #include <string> #include <alsa/asoundlib.h> +#define ERROR_HERE ll->printf("ERROR_HERE: %s %i\n", __FILE__, __LINE__); + +struct SystemStuff +{ + log_t * ll; + + snd_pcm_t *phandle, *chandle; + snd_pcm_uframes_t period_size; + unsigned int rate; + + SystemStuff(log_t * ll) : ll(ll), phandle(NULL), chandle(NULL), period_size(0), rate(0) + { + } + ~SystemStuff() + { + if (phandle) close(0); + } + + void setscheduler(void) + { + struct sched_param sched_param; + + if (sched_getparam(0, &sched_param) < 0) { + ll->printf( "Scheduler getparam failed...\n"); + return; + } + sched_param.sched_priority = sched_get_priority_max(SCHED_RR); + if (!sched_setscheduler(0, SCHED_RR, &sched_param)) { + ll->printf( "Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority); + return; + } + ll->printf( "!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority); + } + + int open(unsigned int rate0, int upsample_max, snd_pcm_uframes_t period0, unsigned int p_per_buff) + { + snd_pcm_hw_params_t *hw; + + if (phandle) + { + ll->printf( "ERROR: open called twice! First close the sound device\n"); + return -1; + } + + if ( 0 > snd_pcm_open(&phandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) { ERROR_HERE; return -1; } + if ( 0 > snd_pcm_open(&chandle, "default", SND_PCM_STREAM_CAPTURE, 0)) { ERROR_HERE; return -1; } + if ( 0 > snd_pcm_hw_params_malloc(&hw)) { ERROR_HERE; snd_pcm_close(phandle); phandle = NULL; return -1; } + + //now we can be a bit flexible with the buffer size and the sample-rate... + + int upsample; + for (upsample = 1; upsample < upsample_max; ++upsample) + { + rate = rate0 * upsample; + + if ( 0 > snd_pcm_hw_params_any(phandle, hw)) { ERROR_HERE; goto open_error;} + + //first do the compulsory steps... interleaved float, 2 channel + if ( 0 > snd_pcm_hw_params_set_rate_resample(phandle, hw, 0)) { ERROR_HERE; goto open_error;} + if ( 0 > snd_pcm_hw_params_test_access(phandle, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;} + if ( 0 > snd_pcm_hw_params_set_access(phandle, hw, SND_PCM_ACCESS_RW_INTERLEAVED)){ ERROR_HERE; goto open_error;} + if ( 0 > snd_pcm_hw_params_test_format(phandle, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;} + if ( 0 > snd_pcm_hw_params_set_format(phandle, hw, SND_PCM_FORMAT_FLOAT)) { ERROR_HERE; goto open_error;} + if ( 0 > snd_pcm_hw_params_set_channels(phandle, hw, 2)) { ERROR_HERE; goto open_error;} + + if ( snd_pcm_hw_params_test_rate(phandle, hw, rate, 0)) + { + ll->printf("test_rate failed( %i\n", rate); + continue; + } + else + { + ll->printf(1, "success! setting rate : %i\n", rate); + if (0 > snd_pcm_hw_params_set_rate(phandle, hw, rate, 0)) { ERROR_HERE; goto open_error;} + + snd_pcm_uframes_t minb=0, maxb= 0; + int mind=0, maxd=0; + snd_pcm_hw_params_get_period_size_min(hw, &minb,&mind); + snd_pcm_hw_params_get_period_size_max(hw, &maxb,&maxd); + ll->printf(2, "FYI: period size range is [%li/%i,%li/%i]\n", minb,mind, maxb, maxd); + + assert(mind == 0); //rate_resample 0 makes this true right? + assert(maxd == 0); //rate_resample 0 makes this true right? + + if (period0 < minb) + { + ll->printf(1, "requested period size (%li) < min (%li), adjusting to min\n", period_size, minb); + period_size = minb; + } + else if (period0 > maxb) + { + ll->printf(2, "requested period size (%li) < max (%li), adjusting to min\n", period_size, maxb); + period_size = maxb; + } + else + { + period_size = period0; + } + + ll->printf(1, "testing period size : %li\n", period_size); + if ( 0 > snd_pcm_hw_params_test_period_size(phandle, hw, period_size, 0)){ ERROR_HERE; goto open_error;} + + + ll->printf(1, "setting period size : %li\n", period_size); + if ( 0 > snd_pcm_hw_params_set_period_size(phandle, hw, period_size, 0)){ ERROR_HERE; goto open_error;} + + ll->printf(1, "setting buffer size : %i * %li = %li\n", p_per_buff, period_size, p_per_buff * period_size); + if ( 0 > snd_pcm_hw_params_set_buffer_size(phandle, hw, p_per_buff*period_size)) { ERROR_HERE; goto open_error;} + + break; + } + } + + if (upsample_max == upsample) { ERROR_HERE; goto open_error; } + + if (0 > snd_pcm_hw_params(phandle, hw)) { ERROR_HERE; goto open_error; } + if (0 > snd_pcm_hw_params(chandle, hw)) { ERROR_HERE; goto open_error; } + + snd_pcm_hw_params_free (hw); + return 0; + +open_error: + snd_pcm_hw_params_free (hw); + snd_pcm_close(phandle); + phandle = NULL; + return -1; + } + void close(int drain = 0) + { + if (!phandle) + { + ll->printf(0, "WARNING: attempt to close already-closed pcm\n"); + return; + } + ll->printf(1, "INFO: closing phandle device\n"); + if (drain) snd_pcm_drain(phandle); + snd_pcm_close(phandle); + snd_pcm_close(chandle); + phandle = NULL; + chandle = NULL; + } + void prepare() + { + if (!phandle) + { + ll->printf(0, "ERROR: attempt to prepare a closed pcm\n"); + return; + } + if (0 > snd_pcm_prepare(phandle)) { ERROR_HERE; } + } + int writebuf(snd_pcm_uframes_t frame_count, float * frame_data) + { + readbuf(frame_count, frame_data); + if (!phandle) + { + ll->printf(0, "ERROR: attempt to write a closed phandle\n"); + return -1; + } + int err; + err = snd_pcm_writei (phandle, frame_data, frame_count ); + if (err == (signed)frame_count) return 0; //success + + assert(err < 0); + + const char * msg = NULL; + snd_pcm_state_t state = snd_pcm_state(phandle); + switch (state) + { + case SND_PCM_STATE_OPEN: msg = "open"; break; + case SND_PCM_STATE_SETUP: msg = "setup"; break; + case SND_PCM_STATE_PREPARED:msg = "prepared"; break; + case SND_PCM_STATE_RUNNING: msg = "running"; break; + case SND_PCM_STATE_XRUN: msg = "xrun"; break; + case SND_PCM_STATE_DRAINING: msg = "draining"; break; + case SND_PCM_STATE_PAUSED: msg = "paused"; break; + case SND_PCM_STATE_SUSPENDED: msg = "suspended"; break; + case SND_PCM_STATE_DISCONNECTED: msg = "disconnected"; break; + } + ll->printf(1, "WARNING: write failed (%s)\tstate = %s\ttime=%lf\n", snd_strerror (err), msg, pytime(NULL)); + if (0 > snd_pcm_recover(phandle, err, 0)) { ERROR_HERE; return err;} + if (0 > snd_pcm_prepare(phandle)) { ERROR_HERE; return err;} + return 1; //warning + } + int readbuf(snd_pcm_uframes_t frame_count, float * frame_data) + { + int err; + err = snd_pcm_readi (chandle, frame_data, frame_count ); + if (err < 0) + { + const char * msg = NULL; + snd_pcm_state_t state = snd_pcm_state(chandle); + switch (state) + { + case SND_PCM_STATE_OPEN: msg = "open"; break; + case SND_PCM_STATE_SETUP: msg = "setup"; break; + case SND_PCM_STATE_PREPARED:msg = "prepared"; break; + case SND_PCM_STATE_RUNNING: msg = "running"; break; + case SND_PCM_STATE_XRUN: msg = "xrun"; break; + case SND_PCM_STATE_DRAINING: msg = "draining"; break; + case SND_PCM_STATE_PAUSED: msg = "paused"; break; + case SND_PCM_STATE_SUSPENDED: msg = "suspended"; break; + case SND_PCM_STATE_DISCONNECTED: msg = "disconnected"; break; + } + ll->printf(1, "WARNING: write failed (%s)\tstate = %s\ttime=%lf\n", snd_strerror (err), msg, pytime(NULL)); + if (0 > snd_pcm_recover(chandle, err, 0)) { ERROR_HERE; return err;} + if (0 > snd_pcm_prepare(chandle)) { ERROR_HERE; return err;} + } + float a = 0.0; + for (unsigned i = 0; i < frame_count; ++i) + { + a = a + frame_data[i] * frame_data[i]; + } + fprintf(stderr, "%lf %i\n", a, err); + if (err == (signed)frame_count) return 0; //success + return -1; + } +}; +#undef ERROR_HERE + struct AlsaStuff { bool good_to_go; diff --git a/Util/Clooper/log.cpp b/Util/Clooper/log.cpp index 2985fca..1749721 100644 --- a/Util/Clooper/log.cpp +++ b/Util/Clooper/log.cpp @@ -32,4 +32,16 @@ struct log_t va_end(ap); fflush(_file); } + void printf( int level, const char * fmt, ... ) __attribute__(( format (printf, 3,4))) + { + if (level <= _level) + { + if (!_file) return; + va_list ap; + va_start(ap,fmt); + ::vfprintf(_file, fmt, ap); + va_end(ap); + fflush(_file); + } + } }; |