From 28070ba58978503c92a703646be76081edf97f43 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 27 Jun 2007 18:08:07 +0000 Subject: probably broken plugin --- (limited to 'Util/Clooper') diff --git a/Util/Clooper/Makefile b/Util/Clooper/Makefile index 3b585f2..a1d1870 100644 --- a/Util/Clooper/Makefile +++ b/Util/Clooper/Makefile @@ -13,7 +13,7 @@ LDFlAGS+=-lpython2.4 all : aclient.so -aclient.so : aclient.cpp +aclient.so : aclient.cpp audio.cpp g++ $(CPPFLAGS) $(CXXFLAGS) -shared -o $@ $< $(LDFLAGS) clean : diff --git a/Util/Clooper/aclient.cpp b/Util/Clooper/aclient.cpp index 0d73c7e..349250a 100644 --- a/Util/Clooper/aclient.cpp +++ b/Util/Clooper/aclient.cpp @@ -14,6 +14,8 @@ #include #include +#include "audio.cpp" + #define ERROR_HERE if (_debug && (VERBOSE > 0)) fprintf(_debug, "ERROR: %s:%i\n", __FILE__, __LINE__) #define IF_DEBUG(N) if (_debug && (VERBOSE > N)) @@ -141,9 +143,9 @@ struct SystemStuff /** the currently opened pcm hande */ snd_pcm_t * pcm; snd_pcm_uframes_t period_size; - unsigned int frame_rate; + unsigned int rate; - SystemStuff() : pcm(NULL), period_size(0), frame_rate(0) + SystemStuff() : pcm(NULL), period_size(0), rate(0) { } ~SystemStuff() @@ -169,7 +171,7 @@ struct SystemStuff int upsample; for (upsample = 1; upsample < upsample_max; ++upsample) { - frame_rate = rate0 * upsample; + rate = rate0 * upsample; if ( 0 > snd_pcm_hw_params_any(pcm, hw)) { ERROR_HERE; goto open_error;} @@ -181,16 +183,16 @@ struct SystemStuff 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", frame_rate); - if ( snd_pcm_hw_params_test_rate(pcm, hw, frame_rate, 0)) + 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", frame_rate); - if (0 > snd_pcm_hw_params_set_rate(pcm, hw, frame_rate, 0)) { ERROR_HERE; goto open_error;} + 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; @@ -521,7 +523,7 @@ struct TamTamSound unsigned int period_per_buffer; int up_ratio; - SystemStuff sys_stuff; + AlsaStuff * sys_stuff; TamTamSound(char * orc, snd_pcm_uframes_t period0, unsigned int ppb) : ThreadID(NULL), PERF_STATUS(STOP), csound(NULL), @@ -531,17 +533,16 @@ struct TamTamSound period0(period0), period_per_buffer(ppb), up_ratio(0), - sys_stuff() + sys_stuff(NULL) { - if (0 > sys_stuff.open(csound_frame_rate, 4, period0, period_per_buffer)) - { - return; - } - sys_stuff.close(0); - up_ratio = sys_stuff.frame_rate / csound_frame_rate; - csound_period_size = (sys_stuff.period_size % up_ratio == 0) - ? sys_stuff.period_size / up_ratio + sys_stuff = new AlsaStuff( "default", "default", SND_PCM_FORMAT_FLOAT, 2, csound_frame_rate, period0, 4, stderr); + if (! sys_stuff->good_to_go ) return; + up_ratio = sys_stuff->rate / csound_frame_rate; + csound_period_size = (sys_stuff->period_size % up_ratio == 0) + ? sys_stuff->period_size / up_ratio : csound_ksmps * 4; + delete sys_stuff; + sys_stuff=NULL; csound = csoundCreate(NULL); int argc=3; @@ -588,28 +589,23 @@ struct TamTamSound if (_debug && (VERBOSE > 2)) fprintf(_debug, "INFO: nsamples = %li nframes = %li\n", csound_nsamples, csound_nframes); - if (0 > sys_stuff.open(csound_frame_rate, 4, period0, period_per_buffer)) - { - IF_DEBUG(0) fprintf(_debug, "ERROR: failed to open alsa device, thread abort\n"); - return 1; - } + sys_stuff = new AlsaStuff( "default", "default", SND_PCM_FORMAT_FLOAT, 2, csound_frame_rate, period0, 4, stderr); + if (!sys_stuff->good_to_go) return 1; - assert(up_ratio = sys_stuff.frame_rate / csound_frame_rate); + assert(up_ratio = sys_stuff->rate / csound_frame_rate); - float *upbuf = new float[ sys_stuff.period_size * nchannels ]; //2 channels + float *upbuf = new float[ sys_stuff->period_size * nchannels ]; //2 channels int cbuf_pos = csound_nframes; float *cbuf = NULL; - unsigned up_pos = 0; + int up_pos = 0; int ratio_pos = 0; - sys_stuff.setscheduler(); //it might work... - while (PERF_STATUS == CONTINUE) { - if (sys_stuff.period_size == (unsigned)csound_nframes ) + if (sys_stuff->period_size == csound_nframes ) { if (csoundPerformBuffer(csound)) break; - if (0 > sys_stuff.write(sys_stuff.period_size, csoundGetOutputBuffer(csound))) break; + if (0 > sys_stuff->writebuf((char*)csoundGetOutputBuffer(csound))) break; } else { @@ -632,11 +628,11 @@ struct TamTamSound ++cbuf_pos; } - if (++up_pos == sys_stuff.period_size) break; + if (++up_pos == sys_stuff->period_size) break; } - if (messed || (up_pos != sys_stuff.period_size)) break; + if (messed || (up_pos != sys_stuff->period_size)) break; - if (0 > sys_stuff.write(sys_stuff.period_size, upbuf)) break; + if (0 > sys_stuff->writebuf((char*)upbuf)) break; } if (thread_playloop) @@ -646,7 +642,7 @@ struct TamTamSound ++nloops; } - sys_stuff.close(1); + delete sys_stuff; if (_debug && (VERBOSE > 2)) fprintf(_debug, "INFO: returning from performance thread\n"); return 0; } diff --git a/Util/Clooper/audio.cpp b/Util/Clooper/audio.cpp new file mode 100644 index 0000000..bd81521 --- /dev/null +++ b/Util/Clooper/audio.cpp @@ -0,0 +1,393 @@ +/* + * Latency test program + * + * Author: Jaroslav Kysela + * + * This small demo program can be used for measuring latency between + * capture and playback. This latency is measured from driver (diff when + * playback and capture was started). Scheduler is set to SCHED_RR. + * + * + * This program 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct AlsaStuff +{ + bool good_to_go; + std::string pdevice, cdevice; + snd_pcm_format_t format; + int rate; + int channels; + int buffer_size; + int period_size; + snd_output_t *output; + snd_pcm_t *phandle, *chandle; + FILE * log; + int frame_bytes; + int allow_resample; + + snd_pcm_hw_params_t *pt_params, *ct_params; /* templates with rate, format and channels */ + snd_pcm_hw_params_t *p_params, *c_params; + snd_pcm_sw_params_t *p_swparams, *c_swparams; + + void link() + { + } + void unlink() + { + assert(!"not impl"); + } + + AlsaStuff( const char * pdev, const char * cdev, snd_pcm_format_t fmt, int chnl, int r0, int p0, int upsample_max, FILE * logfile) + : good_to_go(false), + pdevice(pdev), + cdevice(cdev), + format(fmt), + rate(0), + channels(chnl), + buffer_size(0), + period_size(0), + phandle(NULL), chandle(NULL), + log(logfile), + frame_bytes((snd_pcm_format_width(format) / 8) * channels), + allow_resample(0) + { + + int err; + snd_pcm_uframes_t p_size, c_size, p_psize, c_psize; + unsigned int p_time, c_time; + + snd_pcm_hw_params_alloca(&p_params); + snd_pcm_hw_params_alloca(&c_params); + snd_pcm_hw_params_alloca(&pt_params); + snd_pcm_hw_params_alloca(&ct_params); + snd_pcm_sw_params_alloca(&p_swparams); + snd_pcm_sw_params_alloca(&c_swparams); + + + if ((err = snd_output_stdio_attach(&output, logfile, 0)) < 0) { + fprintf(log, "Output failed: %s\n", snd_strerror(err)); + return; + } + + setscheduler(); + + if ((err = snd_pcm_open(&phandle, pdevice.c_str(), SND_PCM_STREAM_PLAYBACK, 0 )) < 0) { + fprintf(log, "Playback open error: %s\n", snd_strerror(err)); + return; + } + if ((err = snd_pcm_open(&chandle, cdevice.c_str(), SND_PCM_STREAM_CAPTURE, 0 )) < 0) { + fprintf(log, "Record open error: %s\n", snd_strerror(err)); + return; + } + + int upsample=0; + while(upsample < upsample_max) + { + ++upsample; + + rate += r0; + period_size += p0; + + // set stream params + if ((err = setparams_stream(phandle, pt_params, "playback")) < 0) { + fprintf(log, "Unable to set parameters for playback stream: %s\n", snd_strerror(err)); + continue; + } + if ((err = setparams_stream(chandle, ct_params, "capture")) < 0) { + fprintf(log, "Unable to set parameters for playback stream: %s\n", snd_strerror(err)); + continue; + } + + // set buffer params + + if ((err = setparams_bufsize(phandle, p_params, pt_params, period_size, "playback")) < 0) { + printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err)); + continue; + } + if ((err = setparams_bufsize(chandle, c_params, ct_params, period_size, "capture")) < 0) { + printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err)); + continue; + } + + fprintf(stderr, "%s:%i\n", __FILE__, __LINE__); + snd_pcm_hw_params_get_period_size(p_params, &p_psize, NULL); + fprintf(stderr, "\t%i %i\n", (int)p_psize, period_size); + if (p_psize < (unsigned int)period_size) continue; + + fprintf(stderr, "%s:%i\n", __FILE__, __LINE__); + + snd_pcm_hw_params_get_period_size(c_params, &c_psize, NULL); + if (c_psize < (unsigned int)period_size) continue; + + fprintf(stderr, "%s:%i\n", __FILE__, __LINE__); + snd_pcm_hw_params_get_period_time(p_params, &p_time, NULL); + snd_pcm_hw_params_get_period_time(c_params, &c_time, NULL); + if (p_time != c_time) continue; + + fprintf(stderr, "%s:%i\n", __FILE__, __LINE__); + snd_pcm_hw_params_get_buffer_size(p_params, &p_size); + if (p_psize * 2 < p_size) continue; + + fprintf(stderr, "%s:%i\n", __FILE__, __LINE__); + snd_pcm_hw_params_get_buffer_size(c_params, &c_size); + if (c_psize * 2 < c_size) continue; + + if ((err = setparams_set(phandle, p_params, p_swparams, "playback")) < 0) { + printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err)); + continue; + } + if ((err = setparams_set(chandle, c_params, c_swparams, "capture")) < 0) { + printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err)); + continue; + } + break; + } + + if (upsample == upsample_max) return; + + if ((err = snd_pcm_link(chandle, phandle)) < 0) { + printf("Streams link error: %s\n", snd_strerror(err)); + //no big deal... + } + + if ((err = snd_pcm_prepare(phandle)) < 0) { + printf("Prepare error: %s\n", snd_strerror(err)); + return; + } + if ((err = snd_pcm_prepare(chandle)) < 0) { + printf("Prepare error: %s\n", snd_strerror(err)); + return; + } + good_to_go = true; + snd_pcm_dump(phandle, output); + snd_pcm_dump(chandle, output); + char * silence = (char*)malloc(period_size * frame_bytes); + if (snd_pcm_format_set_silence(format, silence, period_size*channels) < 0) { + fprintf(log, "silence error\n"); + } + if (writebuf(silence) < 0) { + fprintf(log, "write error\n"); + good_to_go=false; + } + if (writebuf(silence) < 0) { + fprintf(log, "write error\n"); + good_to_go=false; + } + free(silence); + if ((err = snd_pcm_start(phandle)) < 0) { + fprintf(log, "Go error: %s\n", snd_strerror(err)); + good_to_go=false; + return; + } + if ((err = snd_pcm_start(chandle)) < 0) { + fprintf(log, "Go error: %s\n", snd_strerror(err)); + good_to_go=false; + return; + } + } + ~AlsaStuff() + { + snd_pcm_drop(chandle); + snd_pcm_drain(phandle); + snd_pcm_unlink(chandle); + snd_pcm_hw_free(phandle); + snd_pcm_hw_free(chandle); + snd_pcm_close(phandle); + snd_pcm_close(chandle); + } + + void setscheduler(void) + { + struct sched_param sched_param; + + if (sched_getparam(0, &sched_param) < 0) { + fprintf(log, "Scheduler getparam failed...\n"); + return; + } + sched_param.sched_priority = sched_get_priority_max(SCHED_RR); + if (!sched_setscheduler(0, SCHED_RR, &sched_param)) { + fprintf(log, "Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority); + return; + } + fprintf(log, "!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority); + } + long readbuf(char *buf) + { + if (!good_to_go) return -1; + long frames = period_size; + while( frames ) + { + long r = snd_pcm_readi(chandle, buf, frames); + if (r < 0) return r; + buf += r * frame_bytes; + frames -= r; + } + return 0; + } + long writebuf(const char *buf) + { + long frames = period_size; + if (!good_to_go) return -1; + while ( frames ) { + fprintf(stderr, "before a buf\n"); + long r = snd_pcm_writei(phandle, buf, frames); + fprintf(stderr, "after buf\n"); + if ( r == -EAGAIN ) continue; + if ( r < 0 ) return r; + buf += r * frame_bytes; + frames -= r; + + } + return 0; + } + + int setparams_stream(snd_pcm_t *handle, snd_pcm_hw_params_t *params, const char *id) + { + int err; + unsigned int rrate=rate; + + err = snd_pcm_hw_params_any(handle, params); + if (err < 0) { + printf("Broken configuration for %s PCM: no configurations available: %s\n", snd_strerror(err), id); + return err; + } + err = snd_pcm_hw_params_set_rate_resample(handle, params, allow_resample); + if (err < 0) { + printf("Resample setup failed for %s (val %i): %s\n", id, allow_resample, snd_strerror(err)); + return err; + } + err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); + if (err < 0) { + printf("Access type not available for %s: %s\n", id, snd_strerror(err)); + return err; + } + err = snd_pcm_hw_params_set_format(handle, params, format); + if (err < 0) { + printf("Sample format not available for %s: %s\n", id, snd_strerror(err)); + return err; + } + err = snd_pcm_hw_params_set_channels(handle, params, channels); + if (err < 0) { + printf("Channels count (%i) not available for %s: %s\n", channels, id, snd_strerror(err)); + return err; + } + err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); + if (err < 0) { + printf("Rate %iHz not available for %s: %s\n", rate, id, snd_strerror(err)); + return err; + } + if ((int)rrate != rate) { + printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); + return -EINVAL; + } + return 0; + } + + int setparams_bufsize(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + snd_pcm_hw_params_t *tparams, + snd_pcm_uframes_t bufsize, + const char *id) + { + int err; + snd_pcm_uframes_t periodsize; + + snd_pcm_hw_params_copy(params, tparams); + periodsize = bufsize * 2; + err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize); + if (err < 0) { + printf("Unable to set buffer size %li for %s: %s\n", bufsize * 2, id, snd_strerror(err)); + return err; + } + if (period_size > 0) + periodsize = period_size; + else + periodsize /= 2; + err = snd_pcm_hw_params_set_period_size_near(handle, params, &periodsize, 0); + if (err < 0) { + printf("Unable to set period size %li for %s: %s\n", periodsize, id, snd_strerror(err)); + return err; + } + return 0; + } + + int setparams_set(snd_pcm_t *handle, + snd_pcm_hw_params_t *params, + snd_pcm_sw_params_t *swparams, + const char *id) + { + int err; + + err = snd_pcm_hw_params(handle, params); + if (err < 0) { + printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err)); + return err; + } + err = snd_pcm_sw_params_current(handle, swparams); + if (err < 0) { + printf("Unable to determine current swparams for %s: %s\n", id, snd_strerror(err)); + return err; + } + err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff); + if (err < 0) { + printf("Unable to set start threshold mode for %s: %s\n", id, snd_strerror(err)); + return err; + } + err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); + if (err < 0) { + printf("Unable to set transfer align for %s: %s\n", id, snd_strerror(err)); + return err; + } + err = snd_pcm_sw_params(handle, swparams); + if (err < 0) { + printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err)); + return err; + } + return 0; + } + + void showstat(snd_pcm_t *handle, size_t frames) + { + int err; + snd_pcm_status_t *status; + + snd_pcm_status_alloca(&status); + if ((err = snd_pcm_status(handle, status)) < 0) { + printf("Stream status error: %s\n", snd_strerror(err)); + exit(0); + } + printf("*** frames = %li ***\n", (long)frames); + snd_pcm_status_dump(status, output); + snd_pcm_status_free(status); + } +}; + + + + -- cgit v0.9.1