Initial commit - V1.0

This commit is contained in:
DWW 2022-07-07 19:51:37 +03:00
commit e6e9744529
4 changed files with 502 additions and 0 deletions

9
Makefile Normal file
View File

@ -0,0 +1,9 @@
all:
make apex_mix
make apex_mix_lfe
apex_mix:
gcc -o apex_mix main.c wav_convert.c
apex_mix_lfe:
gcc -o apex_mix_lfe -DLFE_ENABLE main.c wav_convert.c

363
main.c Normal file
View File

@ -0,0 +1,363 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "wav_convert.h"
typedef struct wav_data
{
uint8_t is_be; // Endianess
uint16_t data_fmt; // Format Type
uint16_t channel_count; // Ammount of Channels
uint32_t sample_rate; // Samples per second
uint16_t bits_per_sample; // Bits Per Sample
uint32_t sample_count; // Samples In File
} wav_data;
int read_header(FILE* file, wav_data* header)
{
uint8_t arr[4];
uint8_t riff[4] = {'R', 'I', 'F', 'F'};
uint8_t rifx[4] = {'R', 'I', 'F', 'X'};
uint8_t wave[4] = {'W', 'A', 'V', 'E'};
uint8_t fmt[4] = {'f', 'm', 't', ' '};
uint8_t data[4] = {'d', 'a', 't', 'a'};
uint32_t u32;
uint16_t u16;
if ((NULL == file) || (NULL == header))
{
return -1;
}
fseek(file, 0, SEEK_SET);
fread(arr, sizeof(uint8_t), 4, file);
// Detect RIFF/RIFX
if (0 == strncmp(arr, riff, 4))
{
header->is_be = 0;
}
else if (0 == strncmp(arr, rifx, 4))
{
header->is_be = 1;
}
else
{
printf("RIFF/RIFX\n");
return -1;
}
// File Size Dummy Read
fread(arr, sizeof(uint8_t), 4, file);
// WAVE
fread(arr, sizeof(uint8_t), 4, file);
if (0 != strncmp(arr, wave, 4))
{
printf("WAVE\n");
return -1;
}
// fmt
fread(arr, sizeof(uint8_t), 4, file);
if (0 != strncmp(arr, fmt, 4))
{
printf("fmt\n");
return -1;
}
// Subchunk 1 Size
fread(arr, sizeof(uint8_t), 4, file);
wavtoh32(arr, &u32, header->is_be);
if (16 != u32)
{
printf("fmt Size != 16\n");
}
// Data Format
fread(arr, sizeof(uint8_t), 2, file);
wavtoh16(arr, &u16, header->is_be);
header->data_fmt = u16;
// Channel Count
fread(arr, sizeof(uint8_t), 2, file);
wavtoh16(arr, &u16, header->is_be);
header->channel_count = u16;
// Sample Rate
fread(arr, sizeof(uint8_t), 4, file);
wavtoh32(arr, &u32, header->is_be);
header->sample_rate = u32;
// Byte Rate Dummy Read
fread(arr, sizeof(uint8_t), 4, file);
// Block Align Dummy Read
fread(arr, sizeof(uint8_t), 2, file);
// Bits Per Sample
fread(arr, sizeof(uint8_t), 2, file);
wavtoh16(arr, &u16, header->is_be);
header->bits_per_sample = u16;
// data
fread(arr, sizeof(uint8_t), 4, file);
if (0 != strncmp(arr, data, 4))
{
printf("data\n");
return -1;
}
// Sample Count Read
fread(arr, sizeof(uint8_t), 4, file);
wavtoh32(arr, &u32, header->is_be);
header->sample_count = u32;
u32 = header->channel_count;
u32 *= header->bits_per_sample;
u32 /= 8;
header->sample_count /= u32;
return 0;
}
void write_header(FILE* file, wav_data* header)
{
uint8_t arr[4];
uint32_t u32;
uint16_t u16;
if ((NULL == file) || (NULL == header))
{
return;
}
// RIFF
strncpy(arr, "RIFF", 4);
fwrite(arr, sizeof(uint8_t), 4, file);
// File Size
u32 = header->sample_count;
u32 *= header->channel_count;
u32 *= header->bits_per_sample;
u32 /= 8;
u32 += 36;
htowav32(&u32, arr, 0);
fwrite(arr, sizeof(uint8_t), 4, file);
// WAVE
strncpy(arr, "WAVE", 4);
fwrite(arr, sizeof(uint8_t), 4, file);
// fmt
strncpy(arr, "fmt ", 4);
fwrite(arr, sizeof(uint8_t), 4, file);
// fmt Size
u32 = 16;
htowav32(&u32, arr, 0);
fwrite(arr, sizeof(uint8_t), 4, file);
// Format Type
u16 = header->data_fmt;
htowav16(&u16, arr, 0);
fwrite(arr, sizeof(uint8_t), 2, file);
// Channel Count
u16 = header->channel_count;
htowav16(&u16, arr, 0);
fwrite(arr, sizeof(uint8_t), 2, file);
// Sample Rate
u32 = header->sample_rate;
htowav32(&u32, arr, 0);
fwrite(arr, sizeof(uint8_t), 4, file);
// Byte Rate
u32 = header->sample_rate;
u32 *= header->channel_count;
u32 *= header->bits_per_sample;
u32 /= 8;
htowav32(&u32, arr, 0);
fwrite(arr, sizeof(uint8_t), 4, file);
// Block Align
u16 = header->channel_count;
u16 *= header->bits_per_sample;
u16 /= 8;
htowav16(&u16, arr, 0);
fwrite(arr, sizeof(uint8_t), 2, file);
// Bits Per Sample
u16 = header->bits_per_sample;
htowav16(&u16, arr, 0);
fwrite(arr, sizeof(uint8_t), 2, file);
// data
strncpy(arr, "data", 4);
fwrite(arr, sizeof(uint8_t), 4, file);
// data Size
u32 = header->sample_count;
u32 *= header->channel_count;
u32 *= header->bits_per_sample;
u32 /= 8;
htowav32(&u32, arr, 0);
fwrite(arr, sizeof(uint8_t), 4, file);
}
void print_header(wav_data* header)
{
if (NULL == header)
{
return;
}
if (0 == header->is_be)
{
printf("LE\n");
}
else
{
printf("BE\n");
}
printf("Format: %u\n", header->data_fmt);
printf("Channels: %u\n", header->channel_count);
printf("Sample Rate: %lu\n", header->sample_rate);
printf("Bits: %u\n", header->bits_per_sample);
printf("Samples: %lu\n", header->sample_count);
}
void usage(const char* name)
{
printf("Usage:\n");
printf("\t%s [input] [output] <volume>\n", name);
}
void process_sample(FILE* in, FILE* out, wav_data* header, float volume)
{
union u32tof
{
uint32_t u32;
float f;
} un;
uint8_t u8[4];
float src[8];
float dst[2];
for (int i = 0; i < 8; ++i)
{
src[i] = 0;
}
for (int i = 0; i < header->channel_count; ++i)
{
fread(u8, sizeof(uint8_t), 4, in);
wavtoh32(u8, &un.u32, header->is_be);
src[i] = un.f;
}
#ifdef LFE_ENABLE
// With LFE
dst[0] = src[0] + 0.7071 * src[2] + 0.7071 * src[3] + 0.7071 * src[4] + 0.7071 * src[6];
dst[1] = src[1] + 0.7071 * src[2] + 0.7071 * src[3] + 0.7071 * src[5] + 0.7071 * src[7];
#else
// Without LFE
dst[0] = src[0] + 0.7071 * src[2] + 0.7071 * src[4] + 0.7071 * src[6];
dst[1] = src[1] + 0.7071 * src[2] + 0.7071 * src[5] + 0.7071 * src[7];
#endif
dst[0] *= volume;
dst[1] *= volume;
for (int i = 0; i < 2; ++i)
{
// CLIPPING
if (dst[i] > 0.975)
{
dst[i] = 0.975;
}
if (dst[i] < -0.975)
{
dst[i] = -0.975;
}
un.f = dst[i];
htowav32(&un.u32, u8, 0);
fwrite(u8, sizeof(uint8_t), 4, out);
}
}
int main(int argc, char** argv)
{
FILE *in_file;
FILE *out_file;
wav_data in_header;
wav_data out_header;
float volume = 1.0f;
if (argc < 3)
{
usage(argv[0]);
return -1;
}
in_file = fopen(argv[1], "rb");
if (NULL == in_file)
{
printf("Input File\n");
return -1;
}
if (0 != read_header(in_file, &in_header))
{
fclose(in_file);
printf("Header\n");
return -1;
}
// 1 is PCM, 3 is float
if ((in_header.data_fmt != 3) || (in_header.bits_per_sample != 32) ||
((in_header.channel_count != 8) && (in_header.channel_count != 2)))
{
printf("Weird Header\n");
print_header(&in_header);
fclose(in_file);
return -1;
}
out_file = fopen(argv[2], "wb");
if (NULL == out_file)
{
fclose(in_file);
printf("Output File\n");
return -1;
}
if (argc > 3)
{
volume = atof(argv[3]);
if (0.0 == volume)
{
volume = 1.0;
}
}
out_header = in_header;
out_header.channel_count = 2;
out_header.is_be = 0;
write_header(out_file, &out_header);
// Do processing
for (uint32_t u32 = 0; u32 < in_header.sample_count; ++u32)
{
process_sample(in_file, out_file, &in_header, volume);
}
fclose(in_file);
fclose(out_file);
return 0;
}

118
wav_convert.c Normal file
View File

@ -0,0 +1,118 @@
#include "wav_convert.h"
typedef union wav_u
{
uint8_t u8[4];
uint16_t u16[2];
uint32_t u32;
} wav_u;
uint32_t endian_swap32(uint32_t in)
{
wav_u un;
uint8_t u8[4];
un.u32 = in;
for (int i = 0; i < 4; ++i)
{
u8[i] = un.u8[3 - i];
}
for (int i = 0; i < 4; ++i)
{
un.u8[i] = u8[i];
}
return un.u32;
}
uint16_t endian_swap16(uint16_t in)
{
wav_u un;
uint8_t u8[2];
un.u16[0] = in;
for (int i = 0; i < 2; ++i)
{
u8[i] = un.u8[1 - i];
}
for (int i = 0; i < 2; ++i)
{
un.u8[i] = u8[i];
}
return un.u16[0];
}
void wavtoh32(uint8_t* in, uint32_t* out, uint8_t is_be)
{
wav_u un;
for (int i = 0; i < 4; ++i)
{
un.u8[i] = in[i];
}
if (0 == is_be)
{
*out = un.u32;
}
else
{
*out = endian_swap32(un.u32);
}
}
void wavtoh16(uint8_t* in, uint16_t* out, uint8_t is_be)
{
wav_u un;
for (int i = 0; i < 2; ++i)
{
un.u8[i] = in[i];
}
if (0 == is_be)
{
*out = un.u16[0];
}
else
{
*out = endian_swap16(un.u16[0]);
}
}
void htowav32(uint32_t* in, uint8_t* out, uint8_t is_be)
{
wav_u un;
if (0 == is_be)
{
un.u32 = *in;
}
else
{
un.u32 = endian_swap32(*in);
}
for (int i = 0; i < 4; ++i)
{
out[i] = un.u8[i];
}
}
void htowav16(uint16_t* in, uint8_t* out, uint8_t is_be)
{
wav_u un;
if (0 == is_be)
{
un.u16[0] = *in;
}
else
{
un.u16[0] = endian_swap16(*in);
}
for (int i = 0; i < 2; ++i)
{
out[i] = un.u8[i];
}
}

12
wav_convert.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef WAV_CONVERT_H_
#define WAV_CONVERT_H_
#include <stdint.h>
void wavtoh32(uint8_t* in, uint32_t* out, uint8_t is_be);
void wavtoh16(uint8_t* in, uint16_t* out, uint8_t is_be);
void htowav32(uint32_t* in, uint8_t* out, uint8_t is_be);
void htowav16(uint16_t* in, uint8_t* out, uint8_t is_be);
#endif // WAV_CONVERT_H_