AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs) : AUD_ResampleReader(reader, specs.rate), m_channels(reader->getSpecs().channels), m_position(0) { int error; m_src = src_callback_new(src_callback, SRC_SINC_MEDIUM_QUALITY, m_channels, &error, this); if(!m_src) { // XXX printf("%s\n", src_strerror(error)); AUD_THROW(AUD_ERROR_SRC, state_error); } }
JucePlayer(PropertiesFile *propertiesfile) { this->propertiesfile=propertiesfile; jp_isplaying=false; isreadingdata=false; pleasestop=false; isinitialized=false; isusingjack=false; { num_src_states=0; src_states=NULL; } { ov_callbacks ov_cb={oggread_func,oggseek_func,oggclose_func,oggtell_func}; lastreadoggpos=-1; nextreadoggpos=-1; if(ov_open_callbacks(&oggvorbisfile,&oggvorbisfile,NULL,0,ov_cb)==0) isplaying_ogg=true; else isplaying_ogg=false; N=getSourceLength(); R=44100; oggsrc_state=src_callback_new(audio_getOggResampledData_callback,SRC_QUALITY,2,NULL,NULL); } #ifdef HAVE_JACK samplerate=init_jack(audio_jack_callback); if(samplerate!=-1){ isinitialized=true; isusingjack=true; }else #endif initJuceAudio(); audioDeviceManager.addChangeListener(this); }
void AUD_SRCResampleReader::read(int& length, bool& eos, sample_t* buffer) { AUD_Specs specs = m_reader->getSpecs(); double factor = double(m_rate) / double(specs.rate); specs.rate = m_rate; int size = length; m_buffer.assureSize(length * AUD_SAMPLE_SIZE(specs)); if(specs.channels != m_channels) { src_delete(m_src); m_channels = specs.channels; int error; m_src = src_callback_new(src_callback, SRC_SINC_MEDIUM_QUALITY, m_channels, &error, this); if(!m_src) { // XXX printf("%s\n", src_strerror(error)); AUD_THROW(AUD_ERROR_SRC, state_error); } } m_eos = false; length = src_callback_read(m_src, factor, length, buffer); m_position += length; eos = m_eos && (length < size); }
rove_file_t *rove_file_new_from_path(const char *path) { #ifdef HAVE_SRC int err; #endif rove_file_t *self; SF_INFO info; SNDFILE *snd; if( !(self = calloc(sizeof(rove_file_t), 1)) ) return NULL; file_init(self); if( !(snd = sf_open(path, SFM_READ, &info)) ) { printf("file: couldn't load \"%s\". sorry about your luck.\n%s\n\n", path, sf_strerror(snd)); free(self); return NULL; } self->length = self->file_length = info.frames; self->channels = info.channels; self->sample_rate = info.samplerate; self->file_data = calloc(sizeof(float), info.frames * info.channels); #ifdef HAVE_SRC self->src = src_callback_new(file_src_callback, SRC_SINC_FASTEST, info.channels, &err, self); #endif if( sf_readf_float(snd, self->file_data, info.frames) != info.frames ) { rove_file_free(self); self = NULL; } sf_close(snd); return self; }
static void callback_hang_test (int converter) { static float output [LONG_BUFFER_LEN] ; static SRC_PAIR pairs [] = { { 1.2, 5 }, { 1.1, 1 }, { 1.0, 1 }, { 3.0, 1 }, { 2.0, 1 }, { 0.3, 1 }, { 1.2, 0 }, { 1.1, 10 }, { 1.0, 1 } } ; SRC_STATE *src_state ; double src_ratio = 1.0 ; int k, error ; printf ("\tcallback_hang_test (%-28s) ....... ", src_get_name (converter)) ; fflush (stdout) ; /* Perform sample rate conversion. */ src_state = src_callback_new (input_callback, converter, 1, &error, NULL) ; if (src_state == NULL) { printf ("\n\nLine %d : src_callback_new () failed : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; for (k = 0 ; k < ARRAY_LEN (pairs) ; k++) { alarm (1) ; src_ratio = pairs [k].ratio ; src_callback_read (src_state, src_ratio, pairs [k].count, output) ; } ; src_state = src_delete (src_state) ; alarm (0) ; puts ("ok") ; return ; } /* callback_hang_test */
AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs) : AUD_EffectReader(reader), m_sspecs(reader->getSpecs()), m_factor(double(specs.rate) / double(m_sspecs.rate)), m_tspecs(specs), m_position(0) { m_tspecs.channels = m_sspecs.channels; int error; m_src = src_callback_new(src_callback, SRC_SINC_MEDIUM_QUALITY, m_sspecs.channels, &error, this); if(!m_src) { // XXX printf("%s\n", src_strerror(error)); AUD_THROW(AUD_ERROR_SRC, state_error); } }
static void callback_test (int converter, double src_ratio) { static TEST_CB_DATA test_callback_data ; static float output [BUFFER_LEN] ; SRC_STATE *src_state ; long read_count, read_total ; int input_len, output_len, error ; printf ("\tcallback_test (SRC ratio = %6.4f) ........... ", src_ratio) ; fflush (stdout) ; /* Calculate maximun input and output lengths. */ if (src_ratio >= 1.0) { output_len = BUFFER_LEN ; input_len = (int) floor (BUFFER_LEN / src_ratio) ; } else { input_len = BUFFER_LEN ; output_len = (int) floor (BUFFER_LEN * src_ratio) ; } ; /* Reduce input_len by 10 so output is longer than necessary. */ input_len -= 10 ; if (output_len > BUFFER_LEN) { printf ("\n\nLine %d : output_len > BUFFER_LEN\n\n", __LINE__) ; exit (1) ; } ; test_callback_data.channels = 1 ; test_callback_data.count = 0 ; test_callback_data.total = input_len ; if ((src_state = src_callback_new (test_callback_func, converter, 1, &error, &test_callback_data)) == NULL) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; read_total = 0 ; do { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; read_total += read_count ; } while (read_count > 0) ; if ((error = src_error (src_state)) != 0) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; src_state = src_delete (src_state) ; if (fabs (read_total - src_ratio * input_len) > 2) { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; printf (" input len : %d\n", input_len) ; printf (" output len : %ld (should be %g +/- 2)\n\n", read_total, floor (0.5 + src_ratio * input_len)) ; exit (1) ; } ; puts ("ok") ; return ; } /* callback_test */
static void callback_reset_test (int converter) { static TEST_CB_DATA test_callback_data ; static float output [BUFFER_LEN] ; SRC_STATE *src_state ; double src_ratio = 1.1 ; long read_count, read_total ; int k, error ; printf ("\tcallback_reset_test (%-28s) ....... ", src_get_name (converter)) ; fflush (stdout) ; for (k = 0 ; k < ARRAY_LEN (data_one) ; k++) { data_one [k] = 1.0 ; data_zero [k] = 0.0 ; } ; if ((src_state = src_callback_new (test_callback_func, converter, 1, &error, &test_callback_data)) == NULL) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Process a bunch of 1.0 valued samples. */ test_callback_data.channels = 1 ; test_callback_data.count = 0 ; test_callback_data.total = ARRAY_LEN (data_one) ; test_callback_data.data = data_one ; read_total = 0 ; do { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; read_total += read_count ; } while (read_count > 0) ; /* Check for errors. */ if ((error = src_error (src_state)) != 0) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Reset the state of the converter.*/ src_reset (src_state) ; /* Process a bunch of 0.0 valued samples. */ test_callback_data.channels = 1 ; test_callback_data.count = 0 ; test_callback_data.total = ARRAY_LEN (data_zero) ; test_callback_data.data = data_zero ; /* Now process some zero data. */ read_total = 0 ; do { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; read_total += read_count ; } while (read_count > 0) ; /* Check for errors. */ if ((error = src_error (src_state)) != 0) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Finally make sure that the output data is zero ie reset was sucessful. */ for (k = 0 ; k < BUFFER_LEN / 2 ; k++) if (output [k] != 0.0) { printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n\n", __LINE__, k, output [k]) ; save_oct_float ("output.dat", data_one, ARRAY_LEN (data_one), output, ARRAY_LEN (output)) ; exit (1) ; } ; /* Make sure that this function has been exported. */ src_set_ratio (src_state, 1.0) ; /* Delete converter. */ src_state = src_delete (src_state) ; puts ("ok") ; } /* callback_reset_test */
static void callback_test (int converter, int channel_count, double target_snr) { TEST_CB_DATA test_callback_data ; SRC_STATE *src_state = NULL ; double freq, snr, src_ratio ; int ch, error, frames, read_total, read_count ; printf ("\t%-22s (%d channel%c) ............. ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ; fflush (stdout) ; memset (input_serial, 0, sizeof (input_serial)) ; memset (input_interleaved, 0, sizeof (input_interleaved)) ; memset (output_interleaved, 0, sizeof (output_interleaved)) ; memset (output_serial, 0, sizeof (output_serial)) ; memset (&test_callback_data, 0, sizeof (test_callback_data)) ; frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ; /* Calculate channel_count separate windowed sine waves. */ for (ch = 0 ; ch < channel_count ; ch++) { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; } ; /* Interleave the data in preparation for SRC. */ interleave_data (input_serial, input_interleaved, frames, channel_count) ; /* Perform sample rate conversion. */ src_ratio = 0.95 ; test_callback_data.channels = channel_count ; test_callback_data.total_frames = frames ; test_callback_data.current_frame = 0 ; test_callback_data.data = input_interleaved ; if ((src_state = src_callback_new (test_callback_func, converter, channel_count, &error, &test_callback_data)) == NULL) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; read_total = 0 ; while (read_total < frames) { read_count = src_callback_read (src_state, src_ratio, frames - read_total, output_interleaved + read_total * channel_count) ; if (read_count <= 0) break ; read_total += read_count ; } ; if ((error = src_error (src_state)) != 0) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; src_state = src_delete (src_state) ; if (fabs (read_total - src_ratio * frames) > 2) { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, read_total, (int) floor (src_ratio * frames)) ; printf ("\tsrc_ratio : %.4f\n", src_ratio) ; printf ("\tinput_len : %d\n", frames) ; printf ("\toutput_len : %d\n\n", read_total) ; exit (1) ; } ; /* De-interleave data so SNR can be calculated for each channel. */ deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; for (ch = 0 ; ch < channel_count ; ch++) { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; if (snr < target_snr) { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; exit (1) ; } ; } ; puts ("ok") ; return ; } /* callback_test */
/* All and mighty connection handler. */ static void* rsd_thread(void *thread_data) { connection_t conn; void *data = NULL; wav_header_t w; wav_header_t w_orig; int resample = 0; int rc, written; void *buffer = NULL; #ifdef HAVE_SAMPLERATE SRC_STATE *resample_state = NULL; #else resampler_t *resample_state = NULL; #endif float *resample_buffer = NULL; resample_cb_state_t cb_data; connection_t *temp_conn = thread_data; conn.socket = temp_conn->socket; conn.ctl_socket = temp_conn->ctl_socket; conn.serv_ptr = 0; conn.rate_ratio = 1.0; conn.identity[0] = '\0'; free(temp_conn); if ( debug ) log_printf("Connection accepted, awaiting WAV header data ...\n"); /* Firstly, get the wave header with stream settings. */ rc = get_wav_header(conn, &w); if ( rc == -1 ) { close(conn.socket); close(conn.ctl_socket); log_printf("Couldn't read WAV header... Disconnecting.\n"); pthread_exit(NULL); } memcpy(&w_orig, &w, sizeof(wav_header_t)); if ( resample_freq > 0 && resample_freq != (int)w.sampleRate ) { w.sampleRate = resample_freq; w.bitsPerSample = w_orig.bitsPerSample == 32 ? 32 : 16; if (w_orig.bitsPerSample == 32) w.rsd_format = (is_little_endian()) ? RSD_S32_LE : RSD_S32_BE; else w.rsd_format = (is_little_endian()) ? RSD_S16_LE : RSD_S16_BE; resample = 1; conn.rate_ratio = (float)w.sampleRate * w.bitsPerSample / ((float)w_orig.sampleRate * w_orig.bitsPerSample); } if ( debug ) { log_printf("Successfully got WAV header ...\n"); pheader(&w_orig); if ( resample ) { log_printf("Resamples to:\n"); pheader(&w); } } if ( debug ) log_printf("Initializing %s ...\n", backend->backend); /* Sets up backend */ if ( backend->init(&data) < 0 ) { log_printf("Failed to initialize %s ...\n", backend->backend); goto rsd_exit; } /* Opens device with settings. */ if ( backend->open(data, &w) < 0 ) { log_printf("Failed to open audio driver ...\n"); goto rsd_exit; } backend_info_t backend_info; memset(&backend_info, 0, sizeof(backend_info)); backend->get_backend_info(data, &backend_info); if ( backend_info.chunk_size == 0 ) { log_printf("Couldn't get backend info ...\n"); goto rsd_exit; } if ( backend_info.resample ) { resample = 1; w.sampleRate = w.sampleRate * backend_info.ratio; conn.rate_ratio = backend_info.ratio; w.bitsPerSample = w_orig.bitsPerSample == 32 ? 32 : 16; if (w_orig.bitsPerSample == 32) w.rsd_format = (is_little_endian()) ? RSD_S32_LE : RSD_S32_BE; else w.rsd_format = (is_little_endian()) ? RSD_S16_LE : RSD_S16_BE; } size_t size = backend_info.chunk_size; size_t read_size = size; size_t buffer_size = (read_size > size) ? read_size : size; buffer = malloc(buffer_size); if ( buffer == NULL ) { log_printf("Could not allocate memory for buffer."); goto rsd_exit; } if ( resample ) { resample_buffer = malloc(BYTES_TO_SAMPLES(buffer_size, w.rsd_format) * sizeof(float)); if ( resample_buffer == NULL ) { log_printf("Could not allocate memory for buffer."); goto rsd_exit; } cb_data.format = w_orig.rsd_format; cb_data.data = data; cb_data.conn = &conn; cb_data.framesize = w_orig.numChannels * rsnd_format_to_bytes(w_orig.rsd_format); #ifdef HAVE_SAMPLERATE int err; resample_state = src_callback_new(resample_callback, src_converter, w.numChannels, &err, &cb_data); #else resample_state = resampler_new(resample_callback, (float)w.sampleRate/w_orig.sampleRate, w.numChannels, &cb_data); #endif if ( resample_state == NULL ) { log_printf("Could not initialize resampler."); goto rsd_exit; } } #define MAX_TCP_BUFSIZ (1 << 14) // We only bother with setting buffer size if we're doing TCP. if ( rsd_conn_type == RSD_CONN_TCP ) { int flag = 1; int bufsiz = backend_info.chunk_size * 32; if (bufsiz > MAX_TCP_BUFSIZ) bufsiz = MAX_TCP_BUFSIZ; setsockopt(conn.socket, SOL_SOCKET, SO_RCVBUF, CONST_CAST &bufsiz, sizeof(int)); if ( conn.ctl_socket ) { setsockopt(conn.ctl_socket, SOL_SOCKET, SO_RCVBUF, CONST_CAST &bufsiz, sizeof(int)); setsockopt(conn.ctl_socket, SOL_SOCKET, SO_SNDBUF, CONST_CAST &bufsiz, sizeof(int)); setsockopt(conn.ctl_socket, IPPROTO_TCP, TCP_NODELAY, CONST_CAST &flag, sizeof(int)); } setsockopt(conn.socket, IPPROTO_TCP, TCP_NODELAY, CONST_CAST &flag, sizeof(int)); } /* Now we can send backend info to client. */ if ( send_backend_info(conn, &backend_info) < 0 ) { log_printf("Failed to send backend info ...\n"); goto rsd_exit; } if ( debug ) log_printf("Initializing of %s successful ...\n", backend->backend); if ( debug ) { if ( resample ) { log_printf("Resampling active. %d Hz --> %d Hz ", (int)w_orig.sampleRate, (int)w.sampleRate); #ifdef HAVE_SAMPLERATE log_printf("(libsamplerate)\n"); #else log_printf("(internal quadratic resampler)\n"); #endif } } /* Recieve data, write to sound card. Rinse, repeat :') */ for(;;) { if ( strlen(conn.identity) > 0 && verbose ) { log_printf(" :: %s\n", conn.identity); conn.identity[0] = '\0'; } if ( resample ) { #ifdef HAVE_SAMPLERATE rc = src_callback_read(resample_state, (double)w.sampleRate/(double)w_orig.sampleRate, BYTES_TO_SAMPLES(size, w.rsd_format)/w.numChannels, resample_buffer); if (rsnd_format_to_bytes(w.rsd_format) == 4) src_float_to_int_array(resample_buffer, buffer, BYTES_TO_SAMPLES(size, w.rsd_format)); else src_float_to_short_array(resample_buffer, buffer, BYTES_TO_SAMPLES(size, w.rsd_format)); #else rc = resampler_cb_read(resample_state, BYTES_TO_SAMPLES(size, w.rsd_format)/w.numChannels, resample_buffer); if (rsnd_format_to_bytes(w.rsd_format) == 4) resampler_float_to_s32(buffer, resample_buffer, BYTES_TO_SAMPLES(size, w.rsd_format)); else resampler_float_to_s16(buffer, resample_buffer, BYTES_TO_SAMPLES(size, w.rsd_format)); #endif } else rc = receive_data(data, &conn, buffer, read_size); if ( rc <= 0 ) { if ( debug ) log_printf("Client closed connection.\n"); goto rsd_exit; } for ( written = 0; written < (int)size; ) { rc = backend->write(data, (const char*)buffer + written, size - written); if ( rc == 0 ) goto rsd_exit; written += rc; } } /* Cleanup */ rsd_exit: if ( debug ) log_printf("Closed connection.\n\n"); #ifdef _WIN32 #undef close #endif backend->close(data); #ifdef _WIN32 #define close(x) closesocket(x) #endif free(buffer); close(conn.socket); if (conn.ctl_socket) close(conn.ctl_socket); if (resample_state) { #ifdef HAVE_SAMPLERATE src_delete(resample_state); #else resampler_free(resample_state); #endif } free(resample_buffer); pthread_exit(NULL); }