diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7d7d6e3d..6aab4c22 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ lib_src change log ================== +3.0.0 +----- + + * FIXED: Double buffer asrc_io.input_timestamp to prevent producer timestamp + getting overwritten during asrc processing + * REMOVED: xscope_used argument from the asynchronous_fifo_producer_put() API + 2.5.0 ----- diff --git a/doc/asrc_task/asrc_task.rst b/doc/asrc_task/asrc_task.rst index e8ce7dcb..1a0f0b7e 100644 --- a/doc/asrc_task/asrc_task.rst +++ b/doc/asrc_task/asrc_task.rst @@ -25,7 +25,7 @@ The ASRC Task supports the following nominal sample rates for input and output: - 88.2 kHz - 96 kHz - 176.4 kHz - - 192 kHz + - 192 kHz Because the required compute for multi-channel systems may exceed the performance limit of a single thread, the ASRC subsystem is able to make use of multiple threads in parallel to achieve the required conversion within the sample time period. It uses a dynamic fork and join architecture to share the ASRC workload across multiple threads each time a batch of samples is processed. The threads must all reside on the same tile as the ASRC task due to them sharing input and output buffers. The workload and buffer partitioning is dynamically computed by the ASRC task at stream startup and is constrained by the user at compile time to set maximum limits of both channel count and worker threads. @@ -40,7 +40,7 @@ The difference between the performance requirement between the two architectures - An eight channel system consisting of either 44.1kHz or 48kHz input with maximum output rate of 192kHz will require about (0.15 * (48 + 192) * 8) ~= 288 thread MHz. This can adequately be provided by four threads (assuming up to 8 active threads on an xcore.ai device with a 600MHz clock). -In reality the amount of thread MHz needed will be lower than the above formulae suggest since subsequent ASRC channels after the first can share some of the calculations. This results in about at 10% performance requirement reduction per additional channel per worker thread. Increasing the input frame size in the ASRC task may also reduce the MHz requirement a few % at the cost of larger buffers and a slight latency increase. +In reality the amount of thread MHz needed will be lower than the above formulae suggest since subsequent ASRC channels after the first can share some of the calculations. This results in about at 10% performance requirement reduction per additional channel per worker thread. Increasing the input frame size in the ASRC task may also reduce the MHz requirement a few % at the cost of larger buffers and a slight latency increase. .. warning:: Exceeding the processing time available by specifying a channel count, input/output rates, number of worker threads or device clock speed may result in at best choppy audio or a blocked ASRC task if the overrun is persistent. @@ -102,7 +102,7 @@ An example of the user-defined `C` function for receiving the input samples is s // Receive stream info from producer *new_input_rate = chanend_in_word(c_producer); - asrc_io->input_timestamp = chanend_in_word(c_producer); + asrc_io->input_timestamp[asrc_io->input_write_idx] = chanend_in_word(c_producer); asrc_io->input_channel_count = chanend_in_word(c_producer); // Pack into array properly LRLRLRLR or 123412341234 etc. diff --git a/lib_src/api/asynchronous_fifo.h b/lib_src/api/asynchronous_fifo.h index 5e8461ed..833bbc3f 100644 --- a/lib_src/api/asynchronous_fifo.h +++ b/lib_src/api/asynchronous_fifo.h @@ -59,7 +59,7 @@ typedef struct asynchronous_fifo_t_ { * The ``state`` argument should be an int64_t array of * ``ASYNCHRONOUS_FIFO_INT64_ELEMENTS`` elements that is cast to * ``asynchronous_fifo_t*``. - * + * * That pointer should also be used for all other operations, including operations * both the consumer and producer sides. * @@ -177,8 +177,6 @@ void asynchronous_fifo_exit(asynchronous_fifo_t * UNSAFE state); * * @param timestamp The number of ticks when this sample was input. * - * @param xscope_used Set to 1 if the PID values should be output over - * xscope. Used for debugging. This parameter is subject to be removed in future revisions. * * @returns The current estimate of the mismatch of input and output frequencies. * This is represented as a 32-bit signed number. Zero means no mismatch, @@ -193,8 +191,7 @@ void asynchronous_fifo_exit(asynchronous_fifo_t * UNSAFE state); int32_t asynchronous_fifo_producer_put(asynchronous_fifo_t * UNSAFE state, int32_t * UNSAFE samples, int n, - int32_t timestamp, - int xscope_used); + int32_t timestamp); /** diff --git a/lib_src/lib_build_info.cmake b/lib_src/lib_build_info.cmake index 80411040..71343c4f 100644 --- a/lib_src/lib_build_info.cmake +++ b/lib_src/lib_build_info.cmake @@ -1,5 +1,5 @@ set(LIB_NAME lib_src) -set(LIB_VERSION 2.5.0) +set(LIB_VERSION 3.0.0) set(LIB_DEPENDENT_MODULES "lib_logging(3.2.0)") diff --git a/lib_src/module_build_info b/lib_src/module_build_info index c38608cd..e1007dd1 100644 --- a/lib_src/module_build_info +++ b/lib_src/module_build_info @@ -1,4 +1,4 @@ -VERSION = 2.5.0 +VERSION = 3.0.0 DEPENDENT_MODULES = lib_logging(>=3.2.0) diff --git a/lib_src/src/asrc_task/asrc_task.c b/lib_src/src/asrc_task/asrc_task.c index da0c16b3..363ca9d6 100644 --- a/lib_src/src/asrc_task/asrc_task.c +++ b/lib_src/src/asrc_task/asrc_task.c @@ -82,7 +82,7 @@ void do_asrc_group(schedule_info_t *schedule, uint64_t fs_ratio, asrc_in_out_t * // Pack into the frame this instance of ASRC expects int input_samples[ASRC_N_IN_SAMPLES * MAX_ASRC_CHANNELS_TOTAL]; for(int i = 0; i < ASRC_N_IN_SAMPLES * num_worker_channels; i++){ - // int rd_idx = i % num_worker_channels + (i / num_worker_channels) * asrc_io->asrc_channel_count + worker_channel_start_idx; + // int rd_idx = i % num_worker_channels + (i / num_worker_channels) * asrc_io->asrc_channel_count + worker_channel_start_idx; int rd_idx = i + (asrc_io->asrc_channel_count - num_worker_channels) * (i / num_worker_channels) + worker_channel_start_idx; // Optimisation of above input_samples[i] = asrc_io->input_samples[input_write_idx][rd_idx]; } @@ -193,13 +193,13 @@ void reset_asrc_fifo_consumer(asynchronous_fifo_t * fifo){ } // Default implementation of receive (called from ASRC) which receives samples and config over a channel. This is overridable. -ASRC_TASK_ISR_CALLBACK_ATTR +ASRC_TASK_ISR_CALLBACK_ATTR unsigned receive_asrc_input_samples_cb_default(chanend_t c_asrc_input, asrc_in_out_t *asrc_io, unsigned *new_input_rate){ static unsigned asrc_in_counter = 0; // Get format and timing data from channel *new_input_rate = chanend_in_word(c_asrc_input); - asrc_io->input_timestamp = chanend_in_word(c_asrc_input); + asrc_io->input_timestamp[asrc_io->input_write_idx] = chanend_in_word(c_asrc_input); asrc_io->input_channel_count = chanend_in_word(c_asrc_input); // Pack into array properly LRLRLRLR for 2ch or 123412341234 for 4ch etc. @@ -232,7 +232,7 @@ DEFINE_INTERRUPT_CALLBACK(ASRC_ISR_GRP, asrc_samples_rx_isr_handler, app_data){ chanend_t c_buff_idx = asrc_receive_samples_ctx->c_buff_idx; asrc_in_out_t *asrc_io = asrc_receive_samples_ctx->asrc_io; ASRC_TASK_ISR_CALLBACK_ATTR asrc_task_produce_isr_cb_t receive_asrc_input_samples_cb = asrc_io->asrc_task_produce_cb; - + // Always consume samples so we don't apply backpressure to the producer // Call the user defined receive samples callback. ASRC_TASK_ISR_CALLBACK_ATTR @@ -242,7 +242,7 @@ DEFINE_INTERRUPT_CALLBACK(ASRC_ISR_GRP, asrc_samples_rx_isr_handler, app_data){ if(asrc_in_counter == 0 && asrc_io->ready_flag_to_receive){ // Note if you ever find the code has stopped here then this is due to the time required to ASRC process the input frame // is longer than the period of the frames coming in. To remedy this you need to increase ASRC processing resources or reduce - // the processing requirement. If you are using XCORE-200, consider using xcore.ai for more than 2x the ASRC performance. + // the processing requirement. If you are using XCORE-200, consider using xcore.ai for more than 2x the ASRC performance. // Notify ASRC main loop of new frame chanend_out_byte(c_buff_idx, (uint8_t)asrc_io->input_write_idx); asrc_io->input_write_idx ^= 1; // Swap buffers @@ -274,7 +274,7 @@ static inline void asrc_wait_for_valid_config(chanend_t c_buff_idx, uint32_t *in // Check to see if input params have changed since last process static inline bool asrc_detect_format_change(uint32_t input_frequency, uint32_t output_frequency, asrc_in_out_t *asrc_io){ - if( asrc_io->input_frequency != input_frequency || + if( asrc_io->input_frequency != input_frequency || asrc_io->input_channel_count != asrc_io->asrc_channel_count || asrc_io->output_frequency != output_frequency){ @@ -291,7 +291,7 @@ DEFINE_INTERRUPT_PERMITTED(ASRC_ISR_GRP, void, asrc_processor, asrc_in_out_t *asrc_io, chanend_t c_buff_idx, asynchronous_fifo_t * fifo){ - + uint32_t input_frequency = 0; // Set to invalid for now. We will get rates supplied by producer and consumer. uint32_t output_frequency = 0; @@ -304,7 +304,7 @@ DEFINE_INTERRUPT_PERMITTED(ASRC_ISR_GRP, void, asrc_processor, { 2268, 2268, 1134, 1134, 567, 567}, { 2083, 2083, 1042, 1042, 521, 521} }; - + // Setup a pointer to a struct so the ISR can access these elements asrc_receive_samples_ctx_t asrc_receive_samples_ctx = {c_asrc_input, c_buff_idx, asrc_io}; @@ -322,7 +322,7 @@ DEFINE_INTERRUPT_PERMITTED(ASRC_ISR_GRP, void, asrc_processor, int inputFsCode = frequency_to_fs_code(input_frequency); int outputFsCode = frequency_to_fs_code(output_frequency); int interpolation_ticks = interpolation_ticks_2D[inputFsCode][outputFsCode]; - + //// FIFO init dprintf("FIFO init channels: %d length: %ld\n", asrc_io->asrc_channel_count, fifo->max_fifo_depth); asynchronous_fifo_init(fifo, asrc_io->asrc_channel_count, fifo->max_fifo_depth); @@ -367,8 +367,6 @@ DEFINE_INTERRUPT_PERMITTED(ASRC_ISR_GRP, void, asrc_processor, ideal_fs_ratio = (fs_ratio + (1<<31)) >> 32; dprintf("ideal_fs_ratio: %d\n", ideal_fs_ratio); - const int xscope_used = 0; // Vestige of ASRC API. TODO - cleanup in future when lib_src is tidied - asrc_io->ready_flag_to_receive = 1; // Signal we are ready to consume a frame of input samples asrc_io->ready_flag_configured = 1; // SIgnal we are ready to produce @@ -385,10 +383,10 @@ DEFINE_INTERRUPT_PERMITTED(ASRC_ISR_GRP, void, asrc_processor, int32_t t0 = get_reference_time(); int num_output_samples = par_asrc(num_jobs, schedule, fs_ratio, asrc_io, input_write_idx, sASRCCtrl); - int ts = asrc_timestamp_interpolation(asrc_io->input_timestamp, sASRCCtrl[0], interpolation_ticks); + int ts = asrc_timestamp_interpolation(asrc_io->input_timestamp[input_write_idx], sASRCCtrl[0], interpolation_ticks); // Only push to FIFO if we have samples (FIFO has a bug) otherwise hold last error value if(num_output_samples){ - error = asynchronous_fifo_producer_put(fifo, &asrc_io->output_samples[0], num_output_samples, ts, xscope_used); + error = asynchronous_fifo_producer_put(fifo, &asrc_io->output_samples[0], num_output_samples, ts); } fs_ratio = (((int64_t)ideal_fs_ratio) << 32) + (error * (int64_t) ideal_fs_ratio); @@ -409,7 +407,7 @@ DEFINE_INTERRUPT_PERMITTED(ASRC_ISR_GRP, void, asrc_processor, } -// Wrapper to setup ISR->task signalling chanend and use ISR friendly call to function +// Wrapper to setup ISR->task signalling chanend and use ISR friendly call to function void asrc_task(chanend_t c_asrc_input, asrc_in_out_t *asrc_io, asynchronous_fifo_t *fifo, unsigned fifo_length){ // Check callback is init'd. If not, use default implementation. if (asrc_io->asrc_task_produce_cb == NULL){ diff --git a/lib_src/src/asrc_task/asrc_task.h b/lib_src/src/asrc_task/asrc_task.h index 4184dca4..fd4ab40d 100644 --- a/lib_src/src/asrc_task/asrc_task.h +++ b/lib_src/src/asrc_task/asrc_task.h @@ -27,7 +27,7 @@ #define SRC_DITHER_SETTING 0 #else - // Check for required static defines + // Check for required static defines #include "asrc_task_config.h" #ifndef MAX_ASRC_CHANNELS_TOTAL @@ -53,7 +53,7 @@ #endif /** @brief Decorator for user ASRC producer receive callback. Must be used to allow stack usage calculation. */ -#define ASRC_TASK_ISR_CALLBACK_ATTR __attribute__((fptrgroup("asrc_callback_isr_fptr_grp"))) +#define ASRC_TASK_ISR_CALLBACK_ATTR __attribute__((fptrgroup("asrc_callback_isr_fptr_grp"))) #ifndef __DOXYGEN__ @@ -90,11 +90,11 @@ typedef struct asrc_in_out_t_{ int32_t input_samples[2][ASRC_N_IN_SAMPLES * MAX_ASRC_CHANNELS_TOTAL]; /** Double buffer idx */ unsigned input_write_idx; - /** Timestamp of last received input sample */ - int32_t input_timestamp; - /** Nominal input sample rate 44100..192000 (set by producer) */ + /** Timestamp of last received input sample. Double buffered */ + int32_t input_timestamp[2]; + /** Nominal input sample rate 44100..192000 (set by producer) */ unsigned input_frequency; - /** This is set by the producer and can change dynamically */ + /** This is set by the producer and can change dynamically */ unsigned input_channel_count; /** The function pointer of the ASRC_TASK producer receive callback. Must be defined by user to receive samples from producer over channel. */ void * UNSAFE asrc_task_produce_cb; @@ -111,7 +111,7 @@ typedef struct asrc_in_out_t_{ unsigned asrc_channel_count; /** Flag to indicate ASRC ready to accept samples */ int ready_flag_to_receive; - /** Flag to indicate ASRC is configured and OK to pull from FIFO */ + /** Flag to indicate ASRC is configured and OK to pull from FIFO */ int ready_flag_configured; }asrc_in_out_t; @@ -161,9 +161,9 @@ void reset_asrc_fifo_consumer(asynchronous_fifo_t * UNSAFE fifo); * Prototype that can optionally be defined by the user to initialise the function pointer for the ASRC receive produced samples ISR. * If this is not called then receive_asrc_input_samples_cb_default() is used and the you may call send_asrc_input_samples_default() * from the application to send samples to the ASRC task. - * + * * Must be called before running asrc_task() - * + * * \param asrc_io A pointer to the structure used for holding ASRC IO and state. * \param asrc_rx_fp A pointer to the user asrc_receive_samples function. NOTE - This MUST be decorated by ASRC_TASK_ISR_CALLBACK_ATTR * to allow proper stack calculation by the compiler. See receive_asrc_input_samples_cb_default() in asrc_task.c @@ -176,7 +176,7 @@ void init_asrc_io_callback(asrc_in_out_t * UNSAFE asrc_io, asrc_task_produce_isr /** * If the init_asrc_io_callback() function is not called then a default implementation of the ASRC receive will be used. * This send function (called by the user producer side) mirrors the receive and can be used to push samples into the ASRC. - * + * * \param c_asrc_input The chan end on the application producer side connecting to the ASRC task. * \param input_frequency The sample rate of the input stream (44100, 48000, ...). * \param input_timestamp The ref clock timestamp of latest received input sample. diff --git a/lib_src/src/asynchronous_fifo.c b/lib_src/src/asynchronous_fifo.c index a50e0d1f..f3a3e2ea 100644 --- a/lib_src/src/asynchronous_fifo.c +++ b/lib_src/src/asynchronous_fifo.c @@ -110,8 +110,7 @@ void asynchronous_fifo_reset_consumer(asynchronous_fifo_t *state) { int32_t asynchronous_fifo_producer_put(asynchronous_fifo_t *state, int32_t *samples, int n, - int32_t timestamp, - int xscope_used) { + int32_t timestamp) { int read_ptr = state->read_ptr; int write_ptr = state->write_ptr; int max_fifo_depth = state->max_fifo_depth; @@ -160,21 +159,17 @@ int32_t asynchronous_fifo_producer_put(asynchronous_fifo_t *state, int32_t *samp state->frequency_ratio += (diff_error * (int64_t) (state->Kp / n)) + // TODO: make this lookup table (phase_error * (int64_t) state->Ki); - if (xscope_used) { -#if defined(ASYNC_FIFO_XSCOPE_INSTRUMENTATION) +#if defined(ASYNC_FIFO_XSCOPE_INSTRUMENTATION) xscope_int(1, phase_error); xscope_int(2, diff_error); #endif - } } state->last_phase_error = phase_error; } - if (xscope_used) { -#if defined(ASYNC_FIFO_XSCOPE_INSTRUMENTATION) +#if defined(ASYNC_FIFO_XSCOPE_INSTRUMENTATION) xscope_int(3, len); xscope_int(4, state->frequency_ratio >> K_SHIFT); #endif - } return (state->frequency_ratio + (1<<(K_SHIFT-1))) >> K_SHIFT; } diff --git a/settings.yml b/settings.yml index 541c33d3..c9d59924 100644 --- a/settings.yml +++ b/settings.yml @@ -1,7 +1,7 @@ --- project: lib_src title: SAMPLE RATE CONVERSION -version: 2.5.0 +version: 3.0.0 documentation: exclude_patterns_path: doc/exclude_patterns.inc diff --git a/tests/asrc_task_test/asrc_task_receive_samples.c b/tests/asrc_task_test/asrc_task_receive_samples.c index bdfe2c05..b26162c0 100644 --- a/tests/asrc_task_test/asrc_task_receive_samples.c +++ b/tests/asrc_task_test/asrc_task_receive_samples.c @@ -9,7 +9,7 @@ unsigned receive_asrc_input_samples(chanend_t c_producer, asrc_in_out_t *asrc_io // Receive stream info from producer *new_input_rate = chanend_in_word(c_producer); - asrc_io->input_timestamp = chanend_in_word(c_producer); + asrc_io->input_timestamp[asrc_io->input_write_idx] = chanend_in_word(c_producer); asrc_io->input_channel_count = chanend_in_word(c_producer); // Pack into array properly LRLRLRLR or 123412341234 etc. @@ -29,4 +29,4 @@ unsigned receive_asrc_input_samples(chanend_t c_producer, asrc_in_out_t *asrc_io // Register the above function for ASRC task void setup_asrc_io_custom_callback(asrc_in_out_t *asrc_io){ init_asrc_io_callback(asrc_io, receive_asrc_input_samples); -} \ No newline at end of file +} diff --git a/tests/asynchronous_fifo_asrc_test/Makefile b/tests/asynchronous_fifo_asrc_test/Makefile index d9d53853..baf53ca7 100644 --- a/tests/asynchronous_fifo_asrc_test/Makefile +++ b/tests/asynchronous_fifo_asrc_test/Makefile @@ -1,7 +1,7 @@ TARGET = XCORE-AI-EXPLORER APP_NAME = USED_MODULES = lib_src -XCC_FLAGS = -O3 -fxscope -DASYNC_FIFO_XSCOPE_INSTRUMENTATION +XCC_FLAGS = -O3 -fxscope include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/asynchronous_fifo_asrc_test/src/asynchronous_fifo_asrc_test.c b/tests/asynchronous_fifo_asrc_test/src/asynchronous_fifo_asrc_test.c index 61d8deec..defa3e44 100644 --- a/tests/asynchronous_fifo_asrc_test/src/asynchronous_fifo_asrc_test.c +++ b/tests/asynchronous_fifo_asrc_test/src/asynchronous_fifo_asrc_test.c @@ -92,9 +92,9 @@ int base_frequency_multiplier(int frequency) { extern int async_resets; -DECLARE_JOB(producer, (asynchronous_fifo_t *, int, int, int, int *)); -DECLARE_JOB(consumer, (asynchronous_fifo_t *, int, int)); -DECLARE_JOB(test_async, (int, int, int, int *)); +DECLARE_JOB(producer, (asynchronous_fifo_t *, int, int, int *)); +DECLARE_JOB(consumer, (asynchronous_fifo_t *, int)); +DECLARE_JOB(test_async, (int, int, int *)); #define seconds 10 #define OFFSET 0 // 0x70000000 @@ -160,7 +160,7 @@ static int interpolation_ticks_2D[6][6] = { { 2083, 2083, 1042, 1042, 521, 521} }; -void producer(asynchronous_fifo_t *a, int input_frequency, int output_frequency, int xscope_used, int *errors) { +void producer(asynchronous_fifo_t *a, int input_frequency, int output_frequency, int *errors) { int interpolation_ticks = interpolation_ticks_2D[fs_code(input_frequency)][fs_code(output_frequency)]; asrc_state_t sASRCState[SRC_CHANNELS_PER_INSTANCE]; // ASRC state machine state int iASRCStack[SRC_CHANNELS_PER_INSTANCE][ASRC_STACK_LENGTH_MULT * SRC_N_IN_SAMPLES * 100]; // Buffer between filter stages @@ -225,9 +225,10 @@ void producer(asynchronous_fifo_t *a, int input_frequency, int output_frequency, if (num_samples) { asm volatile("gettime %0" : "=r" (t2)); int ts = asrc_timestamp_interpolation(now, &sASRCCtrl[0], interpolation_ticks); - if (xscope_used) xscope_int(5, fs_ratio >> 32); - error = asynchronous_fifo_producer_put(a, (int32_t *)out_samples, num_samples, ts+OFFSET, - xscope_used); +#if defined(ASYNC_FIFO_XSCOPE_INSTRUMENTATION) + xscope_int(5, fs_ratio >> 32); +#endif + error = asynchronous_fifo_producer_put(a, (int32_t *)out_samples, num_samples, ts+OFFSET); asm volatile("gettime %0" : "=r" (t3)); if (i == 48008) { // printf("%d %d %d %d\n", t1-t0, t2-t1, t3-t2, t3-t0); @@ -255,7 +256,7 @@ void producer(asynchronous_fifo_t *a, int input_frequency, int output_frequency, } } -void consumer(asynchronous_fifo_t *a, int output_frequency, int xscope_used) { +void consumer(asynchronous_fifo_t *a, int output_frequency) { hwtimer_t tmr = hwtimer_alloc(); uint64_t now = hwtimer_get_time(tmr); int freq = POSITIVE_DEVIATION(output_frequency); @@ -274,7 +275,9 @@ void consumer(asynchronous_fifo_t *a, int output_frequency, int xscope_used) { hwtimer_set_trigger_time(tmr, now); (void) hwtimer_get_time(tmr); asynchronous_fifo_consumer_get(a, &output_data, now + OFFSET); - if (xscope_used) xscope_int(0, output_data); +#if defined(ASYNC_FIFO_XSCOPE_INSTRUMENTATION) + xscope_int(0, output_data); +#endif if (i == output_frequency/2) { freq = NEGATIVE_DEVIATION(output_frequency); step = 100000000 / freq; @@ -286,8 +289,7 @@ void consumer(asynchronous_fifo_t *a, int output_frequency, int xscope_used) { #define FIFO_LENGTH 100 -void test_async(int input_frequency, int output_frequency, int xscope_used, - int *errors) { +void test_async(int input_frequency, int output_frequency, int *errors) { int64_t array[ASYNCHRONOUS_FIFO_INT64_ELEMENTS(FIFO_LENGTH, 1)]; asynchronous_fifo_t *asynchronous_fifo_state = (asynchronous_fifo_t *)array; @@ -298,8 +300,8 @@ void test_async(int input_frequency, int output_frequency, int xscope_used, fs_code(output_frequency)); PAR_JOBS( - PJOB(producer, (asynchronous_fifo_state, input_frequency, output_frequency, xscope_used, errors)), - PJOB(consumer, (asynchronous_fifo_state, output_frequency, xscope_used)) + PJOB(producer, (asynchronous_fifo_state, input_frequency, output_frequency, errors)), + PJOB(consumer, (asynchronous_fifo_state, output_frequency)) ); asynchronous_fifo_exit(asynchronous_fifo_state); @@ -309,10 +311,10 @@ int test_44100_low() { int e0=0, e1=0, e2=0, e3=0; printf("Testing 44100 low\n"); PAR_JOBS( - PJOB(test_async, (44100, 44100, 0, &e0)), // OK, 4 sec or so. - PJOB(test_async, (44100, 48000, 0, &e1)), // OK, 4 sec or so. Slight overshoot - PJOB(test_async, (44100, 88200, 0, &e2)), // OK, 4 sec or so. - PJOB(test_async, (44100, 96000, 0, &e3)) // OK 4 sec or so. + PJOB(test_async, (44100, 44100, &e0)), // OK, 4 sec or so. + PJOB(test_async, (44100, 48000, &e1)), // OK, 4 sec or so. Slight overshoot + PJOB(test_async, (44100, 88200, &e2)), // OK, 4 sec or so. + PJOB(test_async, (44100, 96000, &e3)) // OK 4 sec or so. ); return e0 + e1 + e2 + e3; } @@ -321,10 +323,10 @@ int test_48000_low() { int e0=0, e1=0, e2=0, e3=0; printf("Testing 48000 low\n"); PAR_JOBS( - PJOB(test_async, (48000, 44100, 0, &e0)), // OK, 4 sec or so - PJOB(test_async, (48000, 48000, 0, &e1)), // OK 4.16 s stable slight overshoot - PJOB(test_async, (48000, 88200, 0, &e2)), // OK, 4 sec or so - PJOB(test_async, (48000, 96000, 0, &e3)) // OK 4.16 s stable + PJOB(test_async, (48000, 44100, &e0)), // OK, 4 sec or so + PJOB(test_async, (48000, 48000, &e1)), // OK 4.16 s stable slight overshoot + PJOB(test_async, (48000, 88200, &e2)), // OK, 4 sec or so + PJOB(test_async, (48000, 96000, &e3)) // OK 4.16 s stable ); return e0 + e1 + e2 + e3; } @@ -333,10 +335,10 @@ int test_4xx00_high() { int e0, e1, e2, e3; printf("Testing 44100/48000 high\n"); PAR_JOBS( - PJOB(test_async, (44100, 176400, 0, &e2)), // OK, 4 sec or so. - PJOB(test_async, (44100, 192000, 0, &e3)), // OK 4 sec or so. - PJOB(test_async, (48000, 176400, 0, &e0)), // OK, 4 sec or so - PJOB(test_async, (48000, 192000, 0, &e1)) // OK 4.16 s stable + PJOB(test_async, (44100, 176400, &e2)), // OK, 4 sec or so. + PJOB(test_async, (44100, 192000, &e3)), // OK 4 sec or so. + PJOB(test_async, (48000, 176400, &e0)), // OK, 4 sec or so + PJOB(test_async, (48000, 192000, &e1)) // OK 4.16 s stable ); return e0 + e1 + e2 + e3; } @@ -345,10 +347,10 @@ int test_88200_low() { int e0, e1, e2, e3; printf("Testing 88200 low\n"); PAR_JOBS( - PJOB(test_async, (88200, 44100, 0, &e0)), // OK, 4 sec or so - PJOB(test_async, (88200, 48000, 0, &e1)), // OK, 4 sec or so. Slight overshoot, phase error not zero at the end? - PJOB(test_async, (88200, 88200, 0, &e2)), // OK, 4 sec or so. Slight overshoot - PJOB(test_async, (88200, 96000, 0, &e3)) // OK 4 sec or so. Slight overshoot + PJOB(test_async, (88200, 44100, &e0)), // OK, 4 sec or so + PJOB(test_async, (88200, 48000, &e1)), // OK, 4 sec or so. Slight overshoot, phase error not zero at the end? + PJOB(test_async, (88200, 88200, &e2)), // OK, 4 sec or so. Slight overshoot + PJOB(test_async, (88200, 96000, &e3)) // OK 4 sec or so. Slight overshoot ); return e0 + e1 + e2 + e3; } @@ -357,10 +359,10 @@ int test_96000_low() { int e0=0, e1=0, e2=0, e3=0; printf("Testing 96000 low\n"); PAR_JOBS( - PJOB(test_async, (96000, 44100, 0, &e0)), // OK, 4 sec or so. Non zero phase difference - PJOB(test_async, (96000, 48000, 0, &e1)), // OK 4.16 s stable slight overshoot - PJOB(test_async, (96000, 88200, 0, &e2)), // OK, 4 sec or so. Phase error not zero - PJOB(test_async, (96000, 96000, 0, &e3)) // OK 4.14 s stable + PJOB(test_async, (96000, 44100, &e0)), // OK, 4 sec or so. Non zero phase difference + PJOB(test_async, (96000, 48000, &e1)), // OK 4.16 s stable slight overshoot + PJOB(test_async, (96000, 88200, &e2)), // OK, 4 sec or so. Phase error not zero + PJOB(test_async, (96000, 96000, &e3)) // OK 4.14 s stable ); return e0 + e1 + e2 + e3; } @@ -369,10 +371,10 @@ int test_9xx00_high() { int e0=0, e1=0, e2=0, e3=0; printf("Testing 44100/48000 high\n"); PAR_JOBS( - PJOB(test_async, (88200, 176400, 0, &e2)), // OK, 4 sec or so. Slight overshoot - PJOB(test_async, (88200, 192000, 0, &e3)), // OK 4 sec or so. Slight overshoot - PJOB(test_async, (96000, 176400, 0, &e0)), // OK, 4 sec or so. Phase error not zero - PJOB(test_async, (96000, 192000, 0, &e1)) // OK 4.14 s stable + PJOB(test_async, (88200, 176400, &e2)), // OK, 4 sec or so. Slight overshoot + PJOB(test_async, (88200, 192000, &e3)), // OK 4 sec or so. Slight overshoot + PJOB(test_async, (96000, 176400, &e0)), // OK, 4 sec or so. Phase error not zero + PJOB(test_async, (96000, 192000, &e1)) // OK 4.14 s stable ); return e0 + e1 + e2 + e3; } @@ -381,10 +383,10 @@ int test_176400_low() { int e0=0, e1=0, e2=0, e3=0; printf("Testing 176400 low\n"); PAR_JOBS( - PJOB(test_async, (176400, 44100, 0, &e0)), - PJOB(test_async, (176400, 48000, 0, &e1)), - PJOB(test_async, (176400, 88200, 0, &e2)), - PJOB(test_async, (176400, 96000, 0, &e3)) // phase != 0? + PJOB(test_async, (176400, 44100, &e0)), + PJOB(test_async, (176400, 48000, &e1)), + PJOB(test_async, (176400, 88200, &e2)), + PJOB(test_async, (176400, 96000, &e3)) // phase != 0? ); return e0 + e1 + e2 + e3; } @@ -393,10 +395,10 @@ int test_192000_low() { int e0=0, e1=0, e2=0, e3=0; printf("Testing 192000 low\n"); PAR_JOBS( - PJOB(test_async, (192000, 44100, 0, &e0)), - PJOB(test_async, (192000, 48000, 0, &e1)), - PJOB(test_async, (192000, 88200, 0, &e2)), - PJOB(test_async, (192000, 96000, 0, &e3)) + PJOB(test_async, (192000, 44100, &e0)), + PJOB(test_async, (192000, 48000, &e1)), + PJOB(test_async, (192000, 88200, &e2)), + PJOB(test_async, (192000, 96000, &e3)) ); return e0 + e1 + e2 + e3; } @@ -405,10 +407,10 @@ int test_1xxx00_high() { int e0=0, e1=0, e2=0, e3=0; printf("Testing 176400/192000 high\n"); PAR_JOBS( - PJOB(test_async, (176400, 176400, 0, &e2)), - PJOB(test_async, (176400, 192000, 0, &e3)), - PJOB(test_async, (192000, 176400, 0, &e0)), - PJOB(test_async, (192000, 192000, 0, &e1)) + PJOB(test_async, (176400, 176400, &e2)), + PJOB(test_async, (176400, 192000, &e3)), + PJOB(test_async, (192000, 176400, &e0)), + PJOB(test_async, (192000, 192000, &e1)) ); return e0 + e1 + e2 + e3; } @@ -424,7 +426,7 @@ int main(void) { errors += test_9xx00_high(); errors += test_176400_low(); errors += test_192000_low(); - errors += test_1xxx00_high(); + errors += test_1xxx00_high(); if (errors == 0) { printf("PASS\n"); } else {