Skip to content

Instantly share code, notes, and snippets.

@cosmikwolf
Last active December 17, 2019 21:14
Show Gist options
  • Save cosmikwolf/8baf36993642ec1e641d183a9c502134 to your computer and use it in GitHub Desktop.
Save cosmikwolf/8baf36993642ec1e641d183a9c502134 to your computer and use it in GitHub Desktop.
a small c program to perform downsampling on raw audio data
#include <stdio.h>
#include <stdlib.h>
// Tenkai Kariya tenkai@zetaohm.com www.zetaohm.com 12/17/19
// Usage: ./downsample_by2 inputfile.raw outputfile.raw
// downsample will take a raw input audio file and output
// an audio file that has been downsampled to half the
// sample rate. I.E. if you send audio with a 44100 sample rate, it will be
// reduced to 22050
// with SOX installed on OS X, you can play the raw file with the following command
// specifying the correct sample rate and bit depth
// play -r 22500 -e floating-point -b 32 output.raw
// to create a raw audio file from a wav, you can use sox as well:
// sox hexsoc.wav --bits 32 --encoding floating-point tesst.raw
// code was compiled with the following command on os x 10.15.1 with xcode installed:
// gcc downsample_by2.c -o downsample_by2
const float kaiser_smoothing_filter[] = {-0.01452123, -0.0155227, 0.01667252, 0.01800633, -0.01957209, -0.0214361, 0.02369253, 0.02647989, -0.03001054, -0.03462755, 0.04092347, 0.05001757, -0.06430831, -0.09003163, 0.15005272, 0.45015816, 0.45015816, 0.15005272, -0.09003163, -0.06430831, 0.05001757, 0.04092347, -0.03462755, -0.03001054, 0.02647989, 0.02369253, -0.0214361, -0.01957209, 0.01800633, 0.01667252, -0.0155227, -0.01452123};
const int kaiser_smoothing_size = 32;
void decimate_by_2(float *audio_input,
size_t input_length,
float *audio_output);
void downsample_by_2(float *audio_input,
size_t input_length,
float *audio_output,
const float *iir_filter,
const int iir_size);
void convolve(const float Signal[/* SignalLen */], size_t SignalLen,
const float Kernel[/* KernelLen */], size_t KernelLen,
float Result[/* SignalLen + KernelLen - 1 */]);
int main(int argc, char *argv[])
{
if (argc == 3)
{
printf("input file: %s\t output file: %s\n", argv[1], argv[2]);
}
else if (argc > 3)
{
printf("Too many arguments supplied.\n");
exit(1);
}
else
{
printf("One argument expected.\n");
exit(1);
}
printf("sizeof double: %lu\n", sizeof(double));
printf("sizeof float: %lu\n", sizeof(float));
FILE *in_file;
FILE *out_file;
in_file = fopen(argv[1], "r");
if (in_file == NULL)
{
printf("error opening %s", argv[1]);
exit(1);
}
fseek(in_file, 0L, SEEK_END);
int size_in_bytes = ftell(in_file);
rewind(in_file);
printf("file size is: %d \n", size_in_bytes);
int sample_count = size_in_bytes * 8 / 32;
float *input_buffer = malloc(sizeof(float) * sample_count); // convert bytes to 32 bit samples
float *output_buffer = malloc(sizeof(float) * sample_count + 32 - 1); // account for the convolution in the final output size
fread(input_buffer, 4 /*4 bytes per 32bit sample*/, sample_count, in_file);
fclose(in_file);
downsample_by_2(input_buffer, size_in_bytes,
output_buffer,
kaiser_smoothing_filter,
kaiser_smoothing_size);
// decimate_by_2(input_buffer, sample_count, output_buffer);
for (int i = 0; i < 10; i++)
{
printf("%d:\t\t%20.18f\t\t%20.18f\n", i, input_buffer[i], output_buffer[i]);
}
out_file = fopen(argv[2], "wb");
fwrite(output_buffer, sizeof(float), sample_count / 2 + 31 * sizeof(float), out_file);
fclose(out_file);
free(input_buffer);
free(output_buffer);
}
// 2:1 sample rate reduction
// passed output array should have half
// the size of the input array.
void decimate_by_2(float *audio_input,
size_t input_length,
float *audio_output)
{
for (int i = 0; i < input_length / 2; i++)
{
audio_output[i] = audio_input[i * 2];
}
}
void downsample_by_2(float *audio_input,
size_t input_length,
float *audio_output,
const float *iir_filter,
const int iir_size)
{
float *buffer = malloc(sizeof(float) * input_length);
printf("convolving....\n");
convolve(audio_input, input_length,
iir_filter, iir_size, buffer);
printf("decimating....\n");
input_length = input_length + 32 - 1; //account for convolution length
decimate_by_2(buffer, input_length, audio_output);
free(buffer);
printf("downsample complete....\n");
}
// convolve function from:
// https://stackoverflow.com/questions/8424170/1d-linear-convolution-in-ansi-c-code
void convolve(const float Signal[/* SignalLen */], size_t SignalLen,
const float Kernel[/* KernelLen */], size_t KernelLen,
float Result[/* SignalLen + KernelLen - 1 */])
{
size_t n;
for (n = 0; n < SignalLen + KernelLen - 1; n++)
{
size_t kmin, kmax, k;
Result[n] = 0;
kmin = (n >= KernelLen - 1) ? n - (KernelLen - 1) : 0;
kmax = (n < SignalLen - 1) ? n : SignalLen - 1;
for (k = kmin; k <= kmax; k++)
{
Result[n] += Signal[k] * Kernel[n - k];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment