Skip to content

Instantly share code, notes, and snippets.

@harieamjari
Last active August 31, 2022 01:48
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/cc333868d86f6822400b972371eeb941 to your computer and use it in GitHub Desktop.
Save harieamjari/cc333868d86f6822400b972371eeb941 to your computer and use it in GitHub Desktop.
Convolutional reverb in C
#include <stdint.h>
/* float convolutive reverb */
void f_creverb(float *dest, const uint32_t dest_size, const float *src,
const uint32_t src_size, const float *ir,
const uint32_t ir_size) {
for (uint32_t d = 0; (d < dest_size - ir_size) && d < src_size; d++){
for (uint32_t i = 0; i < ir_size; i++)
dest[d + i] += src[d] * ir[i];
}
}
#include "creverb.c"
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
char wav_struct[] = {
'R', 'I', 'F', 'F',
0, 0, 0, 0, /* chunksize */
'W', 'A', 'V', 'E',
'f', 'm', 't', ' ', /* subchunk1id */
16, 0, 0, 0, /* subchunk1size */
1, 0, /* audioformat */
2, 0, /* numchannels */
68, 172, 0, 0, /* samplerate 44100 */
16, 177, 2, 0, /* byterate 88200 */
4, 0, /* blockalign */
16, 0, /* bitspersample */
'd', 'a', 't', 'a', /* subchunk2id */
};
extern int16_t _binary_out_raw_start[], _binary_out_raw_end[];
extern int16_t _binary_ir_raw_start[], _binary_ir_raw_end[];
int main(){
/* get source sound size and impulse response size. */
uint32_t src_size = (uint32_t)(_binary_out_raw_end - _binary_out_raw_start);
uint32_t ir_size = (uint32_t)(_binary_ir_raw_end - _binary_ir_raw_start);
/* allocate left and right channels for src, dest and impulse response. */
float *lnorm_src = calloc((src_size+ir_size)/2, sizeof(float));
float *rnorm_src = calloc((src_size+ir_size)/2, sizeof(float));
float *lnorm_ir = malloc((src_size/2)*sizeof(float));
float *rnorm_ir = malloc((src_size/2)*sizeof(float));
float *ldest = calloc((src_size + ir_size)/2, sizeof(float));
float *rdest = calloc((src_size + ir_size)/2, sizeof(float));
/* normalize values and store as float */
for (uint32_t n = 0; n < src_size/2; n++){
lnorm_src[n] = (float)_binary_out_raw_start[(n+0)*2]/32767.0;
rnorm_src[n] = (float)_binary_out_raw_start[(n+1)*2]/32767.0;
}
for (uint32_t n = 0; n < ir_size/2; n++){
lnorm_ir[n] = (float)_binary_ir_raw_start[(n+0)*2]/32767.0;
rnorm_ir[n] = (float)_binary_ir_raw_start[(n+1)*2]/32767.0;
}
/* we need to divide with 2 to get actual nb_sample of each channel. */
f_creverb(ldest, (src_size+ir_size)/2, lnorm_src, src_size/2, lnorm_ir, ir_size/2);
f_creverb(rdest, (src_size+ir_size)/2, rnorm_src, src_size/2, rnorm_ir, ir_size/2);
free(lnorm_ir); free(rnorm_ir);
free(lnorm_src); free(rnorm_src);
FILE *fp = fopen("rev.wav", "wb");
fwrite(wav_struct, 1, sizeof(wav_struct), fp);
fwrite((uint32_t[]){(src_size+ir_size)*sizeof(int16_t)}, 1, sizeof(uint32_t), fp);
for (int i = 0; i < (src_size+ir_size)/2; i++){
float lv = powf(2.0, -0.0001*fabsf(ldest[i])) - 0.99;
float rv = powf(2.0, -0.0001*fabsf(rdest[i])) - 0.99;
fwrite((int16_t[]){(int16_t)(ldest[i]*32767.0*lv)}, 1, 2, fp);
fwrite((int16_t[]){(int16_t)(rdest[i]*32767.0*rv)}, 1, 2, fp);
}
free(ldest); free(rdest);
fseek(fp, 4, SEEK_SET);
fwrite((uint32_t[]){(src_size+ir_size)*sizeof(int16_t)+36}, 1, sizeof(uint32_t), fp);
fclose(fp);
return 0;
}
LDFLAGS = -lm
CFLAGS = -O3
main: main.c defs.o
defs.o: ir.raw out.raw
$(LD) -r -b binary $^ -o $@
This file has been truncated, but you can view the full file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment