Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * a.out <audiofile> <sampleskew>
- *
- * This program reads in a raw file (assuming 16bit PCM 44.1kHz mono), adjusts
- * the sample rate, and writes the audio to pulseaudio.
- */
- #include <assert.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include <time.h>
- #include <pulse/simple.h>
- #include "libavcodec/avcodec.h"
- #define LENGTH_MS 500 // how many milliseconds of speech to store
- #define RATE 44100 // the sampling rate
- #define FORMAT PA_SAMPLE_S16NE // sample size: 8 or 16 bits
- #define CHANNELS 1 // 1 = mono 2 = stereo
- #define ANGLE_STEP_PER_SEC 15.0 // degrees per second
- #define DEG2RAD( angle ) (((angle)/180.0)*3.14159265)
- /* Globals */
- FILE* infile = 0;
- char* filename = 0;
- int rate_skew = 0; // Num samples to skew
- long file_len = 0;
- pa_simple* pulse_conn;
- pa_sample_spec spec;
- struct AVResampleContext* audio_cntx = 0;
- double angle = 0.0;
- double prev_time = 0.0;
- /* this buffer holds the digitized audio */
- char in_buffer[(LENGTH_MS*RATE*16*CHANNELS)/8000];
- char out_buffer[ sizeof( in_buffer ) * 4];
- /**/
- int calc_skew()
- {
- // Calculate how much time has elapsed sinse the last call.
- struct timeval now_tv;
- gettimeofday( &now_tv, 0 );
- double now = (double)now_tv.tv_sec + ((double)now_tv.tv_usec / 1000000.0);
- double delta = 0.0;
- if( prev_time )
- delta = now - prev_time;
- prev_time = now;
- // Calculate how much to increase the angle by.
- angle += ANGLE_STEP_PER_SEC * delta; // 'delta' is normalized to seconds so this works.
- if( angle >= 360.0 )
- angle = angle - 360.0;
- return( rate_skew * sin( DEG2RAD(angle) ) );
- }
- /**/
- void play_audio()
- {
- size_t bytes_read = 0;
- size_t total_bytes_read = 0;
- // Loop through the file until all data is read.
- for( ; !feof( infile ) && !ferror( infile ); )
- {
- // Read the next chunk of data from the file.
- bytes_read = fread( in_buffer, 1, sizeof( in_buffer ), infile );
- assert( !ferror( infile ) && "Error reading audio file!" );
- total_bytes_read += bytes_read;
- // Resample audio.
- int out_rate = RATE + calc_skew();
- audio_cntx = av_resample_init( out_rate, // out rate
- RATE, // in rate
- 16, // filter length
- 10, // phase count
- 0, // linear FIR filter
- 1.0 ); // cutoff frequency
- assert( audio_cntx && "Failed to create resampling context!" );
- int samples_consumed = 0;
- int samples_output = av_resample( audio_cntx,
- (short*)out_buffer,
- (short*)in_buffer,
- &samples_consumed,
- bytes_read / 2,
- sizeof( out_buffer ) / 2, // in samples
- 0 );
- assert( samples_output > 0 && "Error calling av_resample()!" );
- av_resample_close( audio_cntx );
- // Play the processed samples.
- pa_simple_write( pulse_conn,
- out_buffer,
- samples_output * 2,
- 0 );
- // Display progress text.
- printf( "\rProgress: %2.1f%% Complete, Skew: %2.1f%%, Angle: %2.1f Degrees ",
- ((float)total_bytes_read/(float)file_len)*100.0,
- ((float)(out_rate)/(float)RATE)*100.0,
- angle );
- fflush( stdout );
- }
- printf( "\nDone!\n" );
- }
- /**/
- int main(int argc, char *argv[])
- {
- assert( argc > 2 && "Please specify a file and skew!" );
- filename = argv[1];
- rate_skew = atoi( argv[2] );
- // Initialize ffmpeg resampling.
- avcodec_init();
- // Open audio file.
- infile = fopen( filename, "rb" );
- assert( infile && "Error opening file!" );
- fseek( infile, 0, SEEK_END );
- file_len = ftell( infile );
- fseek( infile, 0, SEEK_SET );
- // Open connection to pulse audio server.
- spec.format = FORMAT;
- spec.channels = CHANNELS;
- spec.rate = RATE;
- pulse_conn = pa_simple_new( NULL, // Use the default server.
- "audio_skew_rate", // Our application's name.
- PA_STREAM_PLAYBACK,
- NULL, // Use the default device.
- "Music", // Description of our stream.
- &spec, // Our sample format.
- NULL, // Use default channel map
- NULL, // Use default buffering attributes.
- NULL ); // Ignore error code.
- // Play audio.
- play_audio();
- // Clean up
- pa_simple_free( pulse_conn );
- fclose( infile );
- return( 0 );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement