UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
wav_reader.h File Reference
#include <stdio.h>
#include <cstdint>
Include dependency graph for wav_reader.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  wav_metadata
 

Macros

#define WAV_HDR_PARSE_INVALID_PARAM   4
 
#define WAV_HDR_PARSE_NOT_PCM   3
 
#define WAV_HDR_PARSE_OK   0
 
#define WAV_HDR_PARSE_READ_ERROR   1
 
#define WAV_HDR_PARSE_WRONG_FORMAT   2
 

Functions

const char * get_wav_error (int errcode)
 
int read_wav_header (FILE *wav_file, struct wav_metadata *metadata)
 
size_t wav_read (void *buffer, size_t sample_count, FILE *wav_file, struct wav_metadata *metadata)
 
int wav_seek (FILE *wav_file, long offset, int whence, struct wav_metadata *metadata)
 same as fseek but WAV header presence is respected (for SEEK SET)
 

Detailed Description

Macro Definition Documentation

◆ WAV_HDR_PARSE_INVALID_PARAM

#define WAV_HDR_PARSE_INVALID_PARAM   4

Definition at line 61 of file wav_reader.h.

Referenced by get_wav_error(), and read_fmt_chunk().

◆ WAV_HDR_PARSE_NOT_PCM

#define WAV_HDR_PARSE_NOT_PCM   3

Definition at line 60 of file wav_reader.h.

Referenced by get_wav_error(), and read_fmt_chunk().

◆ WAV_HDR_PARSE_OK

#define WAV_HDR_PARSE_OK   0

◆ WAV_HDR_PARSE_READ_ERROR

#define WAV_HDR_PARSE_READ_ERROR   1

Definition at line 58 of file wav_reader.h.

Referenced by get_wav_error(), read_fmt_chunk(), and read_wav_header().

◆ WAV_HDR_PARSE_WRONG_FORMAT

#define WAV_HDR_PARSE_WRONG_FORMAT   2

Definition at line 59 of file wav_reader.h.

Referenced by get_wav_error(), read_fmt_chunk(), and read_wav_header().

Function Documentation

◆ get_wav_error()

const char * get_wav_error ( int errcode)

Definition at line 300 of file wav_reader.c.

301{
302 switch(errcode) {
303 case WAV_HDR_PARSE_OK:
304 return "Wav header OK";
306 return "Premature end of WAV file";
308 return "Wav header in wrong format";
310 return "Wav not in PCM";
312 return "Wrong/unsupported value in header";
313 default:
314 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unknown error code %d passed!\n", errcode);
315 return "Unknown error";
316 }
317}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MOD_NAME
Definition wav_reader.c:55
#define WAV_HDR_PARSE_WRONG_FORMAT
Definition wav_reader.h:59
#define WAV_HDR_PARSE_READ_ERROR
Definition wav_reader.h:58
#define WAV_HDR_PARSE_OK
Definition wav_reader.h:57
#define WAV_HDR_PARSE_INVALID_PARAM
Definition wav_reader.h:61
#define WAV_HDR_PARSE_NOT_PCM
Definition wav_reader.h:60

References LOG_LEVEL_ERROR, log_msg(), MOD_NAME, WAV_HDR_PARSE_INVALID_PARAM, WAV_HDR_PARSE_NOT_PCM, WAV_HDR_PARSE_OK, WAV_HDR_PARSE_READ_ERROR, and WAV_HDR_PARSE_WRONG_FORMAT.

Referenced by audio_testcard_read_wav(), and init_audio().

Here is the call graph for this function:

◆ read_wav_header()

int read_wav_header ( FILE * wav_file,
struct wav_metadata * metadata )

This function reads wav header

If read successfully, it leaves read file position at the beginning of data. Currently, only interleaved PCM is supported.

Return values
WAV_HDR_PARSE_OKif ok
WAV_HDR_PARSE_READ_ERRORin case of file read error
WAV_HDR_PARSE_WRONG_FORMATif unsupported wav format
WAV_HDR_PARSE_NOT_PCMnon-PCM WAV detected

< RF64 or BW64

Definition at line 215 of file wav_reader.c.

216{
217 char buffer[16];
218 uint32_t chunk_size;
219 rewind(wav_file);
220
221 _Bool rf64 = 0;
222 READ_N(buffer, 4);
223 if (strncmp(buffer, "RF64", 4) == 0 || strncmp(buffer, "BW64", 4) == 0) {
224 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Using %4.4s WAV file.\n", buffer);
225 rf64 = 1;
226 } else if (strncmp(buffer, "RIFF", 4) != 0) {
227 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Expected RIFF or RF64/BW64 chunk, %.4s given.\n", buffer);
229 }
230
231 // this is the length of the rest of the file, we may ignore
232 READ_N(&chunk_size, 4);
233
234 READ_N(buffer, 4);
235 if (strncmp(buffer, "WAVE", 4) != 0) {
236 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Expected WAVE chunk, %.4s given.\n", buffer);
238 }
239
240 bool found_data_chunk = false;
241 bool found_ds64_chunk = false;
242 bool found_fmt_chunk = false;
243 while (fread(buffer, 4, 1, wav_file) == 1) {
244 READ_N(&chunk_size, 4);
245 if (strncmp(buffer, "data", 4) == 0) {
246 if (!process_data_chunk(wav_file, chunk_size, metadata, found_ds64_chunk)) {
248 }
249 found_data_chunk = true;
250 break;
251 }
252 if (strncmp(buffer, "ds64", 4) == 0) {
253 if (!read_ds64(wav_file, chunk_size, metadata)) {
255 }
256 found_ds64_chunk = true;
257 } else if (strncmp(buffer, "fmt ", 4) == 0) {
258 found_fmt_chunk = true;
259 int rc = read_fmt_chunk(wav_file, metadata, chunk_size);
260 if (rc != WAV_HDR_PARSE_OK) {
261 return rc;
262 }
263 } else { // other tags
264 const char *known_tags[] = { "JUNK", "LIST", "id3 ", NULL }; // "olym" ?
265 int level = is_member(buffer, known_tags) ? LOG_LEVEL_VERBOSE : LOG_LEVEL_WARNING;
266 log_msg(level, MOD_NAME "Skipping chunk \"%4.4s\" sized %" PRIu32 " B!\n", buffer, chunk_size);
267 CHECK(fskip(wav_file, chunk_size), WAV_HDR_PARSE_READ_ERROR);
268 }
269 }
270
271 if (!found_data_chunk) {
272 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Data chunk not found!\n");
274 }
275
276 if (!found_fmt_chunk) {
277 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Fmt chunk not found!\n");
279 }
280
281 if (rf64 && !found_ds64_chunk) { // buggy, but we may try to continue witn implicit data size
282 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Broken WAV - a RF64 file detected but no ds64 chunk found!\n");
283 }
284
285 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "File parsed correctly - length %lld bytes, data offset %lld.\n",
286 metadata->data_size, metadata->data_offset);
287
288 return WAV_HDR_PARSE_OK;
289}
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
long long data_offset
offset from beginning, -1 if unknown (typically unseekable)
Definition wav_reader.h:53
long long data_size
size of data, -1 if unknown
Definition wav_reader.h:54
static int fskip(FILE *f, long off)
Definition wav_reader.c:147
#define READ_N(buf, len)
Definition wav_reader.c:59
static _Bool read_ds64(FILE *wav_file, uint32_t chunk_size, struct wav_metadata *metadata)
Definition wav_reader.c:187
static _Bool process_data_chunk(FILE *wav_file, uint32_t chunk_size, struct wav_metadata *metadata, _Bool found_ds64_chunk)
Definition wav_reader.c:161
static _Bool is_member(const char *needle, const char **haystack)
Definition wav_reader.c:137
#define CHECK(cmd, retval)
Definition wav_reader.c:214
static int read_fmt_chunk(FILE *wav_file, struct wav_metadata *metadata, size_t chunk_size)
Definition wav_reader.c:67

References CHECK, wav_metadata::data_offset, wav_metadata::data_size, fskip(), is_member(), LOG_LEVEL_ERROR, LOG_LEVEL_VERBOSE, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, process_data_chunk(), read_ds64(), read_fmt_chunk(), READ_N, WAV_HDR_PARSE_OK, WAV_HDR_PARSE_READ_ERROR, and WAV_HDR_PARSE_WRONG_FORMAT.

Referenced by audio_testcard_read_wav(), and init_audio().

Here is the call graph for this function:

◆ wav_read()

size_t wav_read ( void * buffer,
size_t sample_count,
FILE * wav_file,
struct wav_metadata * metadata )

Reads sample_count samples from wav_file according to metadata.

Note
conversion to signed is performed if wav sample type is u8

Definition at line 291 of file wav_reader.c.

292{
293 size_t samples = fread(buffer, metadata->ch_count * metadata->bits_per_sample / 8, sample_count, wav_file);
294 if (metadata->bits_per_sample == 8) {
295 signed2unsigned(buffer, buffer, samples * metadata->ch_count * metadata->bits_per_sample / 8);
296 }
297 return samples;
298}
unsigned int ch_count
Definition wav_reader.h:47
unsigned int bits_per_sample
Definition wav_reader.h:49
void signed2unsigned(char *out, const char *in, int in_len)
Definition utils.cpp:515

References wav_metadata::bits_per_sample, wav_metadata::ch_count, and signed2unsigned().

Referenced by audio_reading_thread(), and audio_testcard_read_wav().

Here is the call graph for this function:

◆ wav_seek()

int wav_seek ( FILE * wav_file,
long offset,
int whence,
struct wav_metadata * metadata )

same as fseek but WAV header presence is respected (for SEEK SET)

Definition at line 319 of file wav_reader.c.

320{
321 if (whence == SEEK_CUR || whence == SEEK_END) {
322 return fseek(wav_file, offset, whence);
323 }
324 assert(whence == SEEK_SET);
325 return fseek(wav_file, metadata->data_offset + offset, SEEK_SET);
326}
static __device__ const float offset
Definition cuda_dxt.cu:139

References wav_metadata::data_offset, and offset.

Referenced by audio_reading_thread(), and reset_import().