summaryrefslogtreecommitdiff
path: root/src/wav.h
blob: cba319e0e568ac16e4c10129a998e4f27db3f427 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#pragma once

#include "common.h"
#include "smrt_arena.h"

#include <stdio.h>

typedef struct {
    u64    sample_count;
     u8 *       samples;
} wav_data_t;

// [Master RIFF chunk]
//     FileTypeBlocID  (4 bytes) : Identifier « RIFF »  (0x52, 0x49, 0x46, 0x46)
//     FileSize        (4 bytes) : Overall file size minus 8 bytes
//     FileFormatID    (4 bytes) : Format = « WAVE »  (0x57, 0x41, 0x56, 0x45)
#pragma pack(push, 1)
typedef struct {
     u8        chunk_id[4];
    u32          file_size;
     u8  file_format_id[4];
} wav_master_chunk_t;

// [Chunk describing the data format]
//     FormatBlocID    (4 bytes) : Identifier « fmt␣ »  (0x66, 0x6D, 0x74, 0x20)
//     BlocSize        (4 bytes) : Chunk size minus 8 bytes
//     AudioFormat     (2 bytes) : Audio format (1: PCM integer, 3: IEEE 754 float)
//     NbrChannels     (2 bytes) : Number of channels
//     Frequency       (4 bytes) : Sample rate (in hertz)
//     BytePerSec      (4 bytes) : Number of bytes to read per second (Frequency * BytePerBloc).
//     BytePerBloc     (2 bytes) : Number of bytes per block (NbrChannels * BitsPerSample / 8).
//     BitsPerSample   (2 bytes) : Number of bits per sample
typedef struct {
     u8     chunk_id[4];
    u32      chunk_size;
    u16    audio_format;
    u16    num_channels;
    u32     sample_rate;
    u32   bytes_per_sec;
    u16 bytes_per_block;
    u16 bits_per_sample;
} wav_fmt_chunk_t;
#pragma pack(pop)

/// Load WAV data from wav_file. Data will be allocated on arena, with allocation
/// size aligned up to align_up_memoryn.
wav_data_t load_wav_file(smrt_arena_t *          arena ,
                                 FILE *       wav_file ,
                   wav_master_chunk_t *       master_o ,
                      wav_fmt_chunk_t *       format_o ,
                                  u64 align_up_memoryn);

/// Write WAV headers and data to wav_file.
b32 write_wav_file(FILE *   wav_file ,
        wav_fmt_chunk_t *fmt_chunk_i ,
             wav_data_t       data_i);

/// Generate WAV "fmt " chunk for unsigned 8-bit PCM data ready to be written to a file.
wav_fmt_chunk_t make_wav_fmt_chunk(u32    num_channels ,
                                   u32     sample_rate ,
                                   u16 bits_per_sample);

/// Load WAV data into [-1.0, 1.0] f64 amplitudes. Populates -o inputs with information.
/// samples will be amplitude data for each channel from the WAV file, of length sample_count
/// align_up_memoryn will align allocation up to nearest multiple (For FFT)
void              wav_load(smrt_arena_t *arena, FILE *wav, f64 ***    samples_o ,
                                                           u16 *channel_count_o ,
                                                           u64 * sample_count_o ,
                                                           u32 *  sample_rate_o ,
                                                           u64 align_up_memoryn ,
                                 smrt_arena_t **conflicts, u64    num_conflicts);

f64 *       read_8bps_data(smrt_arena_t *arena, wav_data_t data, u16 num_channels, u16 channel, u64 align_up_memoryn);
f64 *      read_16bps_data(smrt_arena_t *arena, wav_data_t data, u16 num_channels, u16 channel, u64 align_up_memoryn);
f64 *      read_24bps_data(smrt_arena_t *arena, wav_data_t data, u16 num_channels, u16 channel, u64 align_up_memoryn);
f64 *read_32bps_float_data(smrt_arena_t *arena, wav_data_t data, u16 num_channels, u16 channel, u64 align_up_memoryn);

/// Combine channel_count arrays of sample_count samples from **channels
/// Interleaving for WAV format audio storage.
f64 *combine_channels(smrt_arena_t *arena, f64 **channels, u64 channel_count, u64 sample_count);

f32 *f64_to_f32(smrt_arena_t *arena, f64 *samples, u64 sample_count);