void getOggResampledData(float **dst,int num_frames){ double ratio=samplerate/getSourceRate(); long read; #ifdef _MSC_VER // Quite ugly hack. static float *outsound = NULL; static int allocated_num_frames=0; if(num_frames>allocated_num_frames){ outsound = new float(2*num_frames); allocated_num_frames=num_frames; } #else float outsound[num_frames*2]; #endif read=src_callback_read(oggsrc_state,ratio,num_frames,outsound); //fprintf(stderr,"read: %d, num_frames: %d\n",read,num_frames); for(int i=0;i<read;i++){ dst[0][i]=outsound[i*2]; dst[1][i]=outsound[i*2+1]; } if(read<num_frames){ float *newdst[2]={dst[0]+read,dst[1]+read}; getOggResampledData(newdst,num_frames-read); } }
static void file_process(rove_file_t *self, jack_default_audio_sample_t **buffers, int channels, jack_nframes_t nframes, jack_nframes_t sample_rate) { sf_count_t i, o; #ifdef HAVE_SRC float b[2]; double speed; speed = (sample_rate / (double) self->sample_rate) * (1 / self->speed); if( self->speed != 1 || self->sample_rate != sample_rate ) { if( self->channels == 1 ) { for( i = 0; i < nframes; i++ ) { src_callback_read(self->src, speed, 1, b); buffers[0][i] += b[0] * self->volume; buffers[1][i] += b[0] * self->volume; } } else { for( i = 0; i < nframes; i++ ) { src_callback_read(self->src, speed, 1, b); buffers[0][i] += b[0] * self->volume; buffers[1][i] += b[1] * self->volume; } } } else { #endif if( self->channels == 1 ) { for( i = 0; i < nframes; i++ ) { o = rove_file_get_play_pos(self); buffers[0][i] += self->file_data[o] * self->volume; buffers[1][i] += self->file_data[o] * self->volume; rove_file_inc_play_pos(self, 1); } } else { for( i = 0; i < nframes; i++ ) { o = rove_file_get_play_pos(self); buffers[0][i] += self->file_data[o] * self->volume; buffers[1][i] += self->file_data[++o] * self->volume; rove_file_inc_play_pos(self, 1); } } #ifdef HAVE_SRC } #endif }
void AUD_SRCResampleReader::read(int & length, sample_t* & buffer) { int size = length * AUD_SAMPLE_SIZE(m_tspecs); if(m_buffer.getSize() < size) m_buffer.resize(size); buffer = m_buffer.getBuffer(); length = src_callback_read(m_src, m_factor, length, buffer); m_position += length; }
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); }
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 */
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); }