Skip to content

Instantly share code, notes, and snippets.

@harieamjari
Last active June 15, 2020 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harieamjari/cea6858b78b4f1545386c1a989aaa575 to your computer and use it in GitHub Desktop.
Save harieamjari/cea6858b78b4f1545386c1a989aaa575 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <fftw3.h>
#define FPS 24
#define VID_TIME 10
typedef struct __attribute__((__packed__)) {
char ChunkID[4];
uint32_t ChunkSize;
char Format[4]; char Subchunk1ID[4];
uint32_t Subchunk1Size;
uint16_t AudioFormat;
uint16_t NumChannels;
uint32_t SampleRate;
uint32_t ByteRate;
uint16_t BlockAlign;
uint16_t BitsPerSample;
} wav_header_struct;
/* prints the structure of a wav_struct */
void print_wav_struct(wav_header_struct wav_file);
/* num of samples */
uint32_t NumOfSamples(wav_header_struct wav_file, FILE *fp);
/* subchunk2 size */
uint32_t Subchunk2Size(FILE *fp);
int main(){
int16_t *raw_PCM;
char command[300];
FILE *fp = fopen("write.wav", "rb");
if (!fp) return 1;
FILE *pl_data;
wav_header_struct wav_file1;
fread(&wav_file1,sizeof(wav_file1),1,fp);
if (strncmp(wav_file1.ChunkID, "RIFF", 4)) return 2; // not a riff file. check with `echo $?'
if (wav_file1.NumChannels == 2) return 3; // must be a mono file! check with `echo $?'
uint32_t wav_samples = NumOfSamples(wav_file1, fp);
fftw_complex *in, *out;
fftw_plan my_plan;
double begin = 1837.5;
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*begin);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*begin);
my_plan = fftw_plan_dft_1d((int) begin+1, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
raw_PCM = malloc(sizeof(int16_t)*wav_samples);
fread(raw_PCM, sizeof(int16_t), wav_samples, fp);
fclose(fp);
for (int frame = 0; frame < FPS*(int)(wav_samples/wav_file1.SampleRate); frame++){
pl_data = fopen("pl.dat", "w");
for (int i = (int)begin*frame; i < (int)begin*(frame+1); i++){
in[i-(int)begin*frame][0] = (double) raw_PCM[i];
in[i-(int)begin*frame][1] = 0.0;
}
fftw_execute(my_plan);
for (int i = 0; i < (int) (100*FPS); i++){
fprintf(pl_data, "%f %f\n", (double) i*FPS, sqrt(pow(out[i][0],2)+pow(out[i][1],2)));
}
fclose(pl_data);
sprintf(command, "gnuplot -e \"set term png; set xlabel \'frame-%03d\'; plot [0:2400] [0:8*10**5] \'pl.dat\' with lines\" > plot-%03d", frame, frame);
printf("%s\n", command);
system(command);
}
/*
int begin = 0;
for (int i = begin; i < wav_samples; i++){
in[i-begin][0] = (double) raw_PCM[i];
in[i-begin][1] = 0.0;
}
free(raw_PCM);
fftw_execute(my_plan);
*/
free(raw_PCM);
fftw_destroy_plan(my_plan);
fftw_free(in); fftw_free(out);
return 0; // check with `echo $?'
}
/*
void print_wav_struct(wav_header_struct wav_file){
printf("ChunkID: %.*s\n", 4, wav_file.ChunkID);
printf("ChunkSize: %d\n", wav_file.ChunkSize);
printf("Format: %.*s\n", 4, wav_file.Format);
printf("Subchunk1ID: %.*s\n", 4, wav_file.Subchunk1ID);
printf("Subchunk1Size: %d\n", wav_file.Subchunk1Size);
printf("AudioFormat: %hu\n", wav_file.AudioFormat);
printf("NumChannels: %hu\n", wav_file.NumChannels);
printf("SampleRate: %d\n", wav_file.SampleRate); printf("ByteRate: %d\n", wav_file.ByteRate);
printf("BlockAlign: %hu\n", wav_file.BlockAlign); printf("BitsPerSample: %hu\n", wav_file.BitsPerSample);
}
*/
uint32_t NumOfSamples(wav_header_struct wav_file, FILE *fp){
uint32_t dummy_NumOfSamples = (uint32_t) (8*((double) Subchunk2Size(fp)/wav_file.BitsPerSample));
return dummy_NumOfSamples;
}
uint32_t Subchunk2Size(FILE *fp){
char Subchunk2ID[4];
uint32_t wav_size;
fseek(fp, 36, SEEK_SET);
do {
fread(Subchunk2ID, 4, 1, fp);
fseek(fp, -3, SEEK_CUR);
} while(strncmp(Subchunk2ID, "data", 4));
fseek(fp, 3, SEEK_CUR);
fread(&wav_size, 4, 1, fp);
return wav_size;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment