summaryrefslogtreecommitdiff
path: root/3rdparty/libwav/include/wav.h
blob: 1178622f95b5c51218bbb3ba31e8d070784ebd4d (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/** Simple PCM wav file I/O library
 *
 * Author: Zhaosheng Pan <zhaosheng.pan@sololand.moe>
 *
 * The API is designed to be similar to stdio.
 *
 * This library does not support:
 *
 *   - formats other than PCM, IEEE float and log-PCM
 *   - extra chunks after the data chunk
 *   - big endian platforms (might be supported in the future)
 */

#ifndef __WAV_H__
#define __WAV_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdarg.h>
#include <stddef.h>

#if !defined(_MSC_VER) || _MSC_VER >= 1800
#define WAV_INLINE static inline
#define WAV_CONST const
#define WAV_RESTRICT restrict
#else
#define WAV_INLINE static __inline
#define WAV_CONST
#define WAV_RESTRICT __restrict
#endif

#if defined(__APPLE__) || defined(_MSC_VER)
typedef long long           WavI64;
typedef unsigned long long  WavU64;
typedef long long           WavIntPtr;
typedef unsigned long long  WavUIntPtr;
#else
#if defined(_WIN64) || defined(__x86_64) || defined(__amd64)
typedef long                WavI64;
typedef unsigned long       WavU64;
typedef long                WavIntPtr;
typedef unsigned long       WavUIntPtr;
#else
typedef long long           WavI64;
typedef unsigned long long  WavU64;
typedef int                 WavIntPtr;
typedef unsigned int        WavUIntPtr;
#endif
#endif

#if defined(__cplusplus) && __cplusplus >= 201103L
#define WAV_THREAD_LOCAL thread_local
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define WAV_THREAD_LOCAL _Thread_local
#elif defined(_MSC_VER)
#define WAV_THREAD_LOCAL __declspec(thread)
#else
#define WAV_THREAD_LOCAL __thread
#endif

typedef int                 WavBool;
typedef signed char         WavI8;
typedef unsigned char       WavU8;
typedef short               WavI16;
typedef unsigned short      WavU16;
typedef int                 WavI32;
typedef unsigned int        WavU32;

enum {
    WAV_FALSE,
    WAV_TRUE
};

/* wave file format codes */
#define WAV_FORMAT_PCM          ((WavU16)0x0001)
#define WAV_FORMAT_IEEE_FLOAT   ((WavU16)0x0003)
#define WAV_FORMAT_ALAW         ((WavU16)0x0006)
#define WAV_FORMAT_MULAW        ((WavU16)0x0007)
#define WAV_FORMAT_EXTENSIBLE   ((WavU16)0xfffe)

typedef enum {
    WAV_OK,         /** no error */
    WAV_ERR_OS,     /** error when {wave} called a stdio function */
    WAV_ERR_FORMAT, /** not a wave file or unsupported wave format */
    WAV_ERR_MODE,   /** incorrect mode when opening the wave file or calling mode-specific API */
    WAV_ERR_PARAM,  /** incorrect parameter passed to the API function */
} WavErrCode;

typedef struct {
    WavErrCode  code;
    char*       message;
    int         _is_literal;
} WavErr;

typedef struct {
    void*   (*malloc)(void *context, size_t size);
    void*   (*realloc)(void *context, void *p, size_t size);
    void    (*free)(void *context, void *p);
} WavAllocFuncs;

void wav_set_allocator(void *context, WAV_CONST WavAllocFuncs *funcs);

void* wav_malloc(size_t size);
void* wav_realloc(void *p, size_t size);
void wav_free(void *p);

char* wav_strdup(WAV_CONST char *str);
char* wav_strndup(WAV_CONST char *str, size_t n);
int wav_vasprintf(char **str, WAV_CONST char *format, va_list args);
int wav_asprintf(char **str, WAV_CONST char *format, ...);

WAV_CONST WavErr* wav_err(void);
void wav_err_clear(void);

#define WAV_OPEN_READ       1
#define WAV_OPEN_WRITE      2
#define WAV_OPEN_APPEND     4

typedef struct _WavFile WavFile;

/** Open a wav file
 *
 *  @param filename     The name of the wav file
 *  @param mode         The mode for open (same as {fopen})
 *  @return             NULL if the memory allocation for the {WavFile} object failed. Non-NULL means the memory allocation succeeded, but there can be other errors, which can be obtained using {wav_errno} or {wav_error}.
 */
WavFile* wav_open(WAV_CONST char* filename, WavU32 mode);
void     wav_close(WavFile* self);
WavFile* wav_reopen(WavFile* self, WAV_CONST char* filename, WavU32 mode);

/** Read a block of samples from the wav file
 *
 *  @param buffer       A pointer to a buffer where the data will be placed
 *  @param count        The number of frames (block size)
 *  @param self         The pointer to the {WavFile} structure
 *  @return             The number of frames read. If returned value is less than {count}, either EOF reached or an error occured
 *  @remarks            This API does not support extensible format. For extensible format, use {wave_read_raw} instead.
 */
size_t wav_read(WavFile* self, void *buffer, size_t count);

/** Write a block of samples to the wav file
 *
 *  @param buffer   A pointer to the buffer of data
 *  @param count    The number of frames (block size)
 *  @param self     The pointer to the {WavFile} structure
 *  @return         The number of frames written. If returned value is less than {count}, either EOF reached or an error occured.
 *  @remarks        This API does not support extensible format. For extensible format, use {wave_read_raw} instead.
 */
size_t wav_write(WavFile* self, WAV_CONST void *buffer, size_t count);

/** Tell the current position in the wav file.
 *
 *  @param self     The pointer to the WavFile structure.
 *  @return         The current frame index.
 */
long int wav_tell(WAV_CONST WavFile* self);

int  wav_seek(WavFile* self, long int offset, int origin);
void wav_rewind(WavFile* self);

/** Tell if the end of the wav file is reached.
 *
 *  @param self     The pointer to the WavFile structure.
 *  @return         Non-zero integer if the end of the wav file is reached, otherwise zero.
 */
int wav_eof(WAV_CONST WavFile* self);

int wav_flush(WavFile* self);

/** Set the format code
 *
 *  @param self     The {WavFile} object
 *  @param format   The format code, which should be one of `WAV_FORMAT_*`
 *  @remarks        All data will be cleared after the call. {wav_errno} can be used to get the error code if there is an error.
 */
void wav_set_format(WavFile* self, WavU16 format);

/** Set the number of channels
 *
 *  @param self             The {WavFile} object
 *  @param num_channels     The number of channels
 *  @remarks                All data will be cleared after the call. {wav_errno} can be used to get the error code if there is an error.
 */
void wav_set_num_channels(WavFile* self, WavU16 num_channels);

/** Set the sample rate
 *
 *  @param self             The {WavFile} object
 *  @param sample_rate      The sample rate
 *  @remarks                All data will be cleared after the call. {wav_errno} can be used to get the error code if there is an error.
 */
void wav_set_sample_rate(WavFile* self, WavU32 sample_rate);

/** Get the number of valid bits per sample
 *
 *  @param self     The {WavFile} object
 *  @param bits     The value of valid bits to set
 *  @remarks        If {bits} is 0 or larger than 8*{sample_size}, an error will occur. All data will be cleared after the call. {wav_errno} can be used to get the error code if there is an error.
 */
void wav_set_valid_bits_per_sample(WavFile* self, WavU16 bits);

/** Set the size (in bytes) per sample
 *
 *  @param self             The WaveFile object
 *  @param sample_size      Number of bytes per sample
 *  @remarks                When this function is called, the {BitsPerSample} and {ValidBitsPerSample} fields in the wav file will be set to 8*{sample_size}. All data will be cleared after the call. {wav_errno} can be used to get the error code if there is an error.
 */
void wav_set_sample_size(WavFile* self, size_t sample_size);

WavU16 wav_get_format(WAV_CONST WavFile* self);
WavU16 wav_get_num_channels(WAV_CONST WavFile* self);
WavU32 wav_get_sample_rate(WAV_CONST WavFile* self);
WavU16 wav_get_valid_bits_per_sample(WAV_CONST WavFile* self);
size_t wav_get_sample_size(WAV_CONST WavFile* self);
size_t wav_get_length(WAV_CONST WavFile* self);
WavU32 wav_get_channel_mask(WAV_CONST WavFile* self);
WavU16 wav_get_sub_format(WAV_CONST WavFile* self);

#ifdef __cplusplus
}
#endif

#endif /* __WAV_H__ */