ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
wav_writer.c
Go to the documentation of this file.
1
6#include <ascii-chat/audio/wav_writer.h>
7#include <ascii-chat/common.h>
8#include <ascii-chat/platform/string.h>
9#include <ascii-chat/platform/util.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <stdint.h>
14
15// WAV file header structures
16#pragma pack(push, 1)
20typedef struct {
21 char riff[4];
22 uint32_t file_size;
23 char wave[4];
25
29typedef struct {
30 char fmt[4];
31 uint32_t chunk_size;
32 uint16_t audio_format;
33 uint16_t num_channels;
34 uint32_t sample_rate;
35 uint32_t byte_rate;
36 uint16_t block_align;
37 uint16_t bits_per_sample;
39
43typedef struct {
44 char data[4];
45 uint32_t data_size;
47#pragma pack(pop)
48
49wav_writer_t *wav_writer_open(const char *filepath, int sample_rate, int channels) {
50 if (!filepath || sample_rate <= 0 || channels <= 0 || channels > 2) {
51 return NULL;
52 }
53
54 wav_writer_t *writer = SAFE_MALLOC(sizeof(wav_writer_t), wav_writer_t *);
55 if (!writer) {
56 return NULL;
57 }
58
59 writer->file = platform_fopen(filepath, "wb");
60 if (!writer->file) {
61 SAFE_FREE(writer);
62 return NULL;
63 }
64
65 writer->samples_written = 0;
66 writer->sample_rate = sample_rate;
67 writer->channels = channels;
68
69 // Write WAV header (we'll update sizes when closing)
70 wav_riff_header_t riff = {.riff = {'R', 'I', 'F', 'F'},
71 .file_size = 0, // Will update on close
72 .wave = {'W', 'A', 'V', 'E'}};
73
74 wav_fmt_chunk_t fmt = {.fmt = {'f', 'm', 't', ' '},
75 .chunk_size = 16,
76 .audio_format = 3, // IEEE float
77 .num_channels = (uint16_t)channels,
78 .sample_rate = (uint32_t)sample_rate,
79 .byte_rate = (uint32_t)(sample_rate * channels * sizeof(float)),
80 .block_align = (uint16_t)(channels * sizeof(float)),
81 .bits_per_sample = 32};
82
83 wav_data_header_t data = {
84 .data = {'d', 'a', 't', 'a'},
85 .data_size = 0 // Will update on close
86 };
87
88 fwrite(&riff, sizeof(riff), 1, writer->file);
89 fwrite(&fmt, sizeof(fmt), 1, writer->file);
90 fwrite(&data, sizeof(data), 1, writer->file);
91
92 return writer;
93}
94
95int wav_writer_write(wav_writer_t *writer, const float *samples, int num_samples) {
96 if (!writer || !writer->file || !samples || num_samples <= 0) {
97 return -1;
98 }
99
100 size_t written = fwrite(samples, sizeof(float), num_samples, writer->file);
101 if (written != (size_t)num_samples) {
102 return -1;
103 }
104
105 writer->samples_written += num_samples;
106
107 // Flush immediately to ensure data is written to disk (critical for real-time analysis)
108 fflush(writer->file);
109
110 return 0;
111}
112
113void wav_writer_close(wav_writer_t *writer) {
114 if (!writer) {
115 return;
116 }
117
118 if (writer->file) {
119 // Update file size and data size in header
120 uint32_t data_size = (uint32_t)(writer->samples_written * sizeof(float));
121 uint32_t file_size = data_size + 36; // 36 = header size without RIFF chunk
122
123 // Seek to file size field (offset 4)
124 fseek(writer->file, 4, SEEK_SET);
125 fwrite(&file_size, sizeof(uint32_t), 1, writer->file);
126
127 // Seek to data size field (offset 40)
128 fseek(writer->file, 40, SEEK_SET);
129 fwrite(&data_size, sizeof(uint32_t), 1, writer->file);
130
131 // Flush all buffered data to ensure headers are written before closing
132 fflush(writer->file);
133 fclose(writer->file);
134 }
135
136 SAFE_FREE(writer);
137}
138
140 const char *env = SAFE_GETENV("ASCIICHAT_DUMP_AUDIO");
141 return env && (strcmp(env, "1") == 0 || strcmp(env, "true") == 0);
142}
WAV data chunk header preceding audio samples.
Definition wav_writer.c:43
char data[4]
"data" chunk identifier
Definition wav_writer.c:44
uint32_t data_size
Size of data section in bytes.
Definition wav_writer.c:45
WAV format chunk describing audio format parameters.
Definition wav_writer.c:29
char fmt[4]
"fmt " chunk identifier
Definition wav_writer.c:30
uint16_t num_channels
Number of channels (1 = mono, 2 = stereo)
Definition wav_writer.c:33
uint32_t byte_rate
Bytes per second (sample_rate * num_channels * bytes_per_sample)
Definition wav_writer.c:35
uint16_t audio_format
Audio format (3 = IEEE float)
Definition wav_writer.c:32
uint16_t bits_per_sample
Bits per sample (32 for float)
Definition wav_writer.c:37
uint32_t chunk_size
Chunk size (16 for PCM)
Definition wav_writer.c:31
uint32_t sample_rate
Sample rate in Hz (e.g., 44100)
Definition wav_writer.c:34
uint16_t block_align
Block alignment (num_channels * bytes_per_sample)
Definition wav_writer.c:36
WAV RIFF header (first 12 bytes of WAV file)
Definition wav_writer.c:20
uint32_t file_size
File size - 8 bytes.
Definition wav_writer.c:22
char riff[4]
"RIFF" identifier
Definition wav_writer.c:21
FILE * platform_fopen(const char *filename, const char *mode)
bool wav_dump_enabled(void)
Definition wav_writer.c:139
wav_writer_t * wav_writer_open(const char *filepath, int sample_rate, int channels)
Definition wav_writer.c:49
int wav_writer_write(wav_writer_t *writer, const float *samples, int num_samples)
Definition wav_writer.c:95
void wav_writer_close(wav_writer_t *writer)
Definition wav_writer.c:113