porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c
Go to the documentation of this file.
1 #define DR_FLAC_IMPLEMENTATION
2 #include "../../dr_flac.h"
3 
4 /* libFLAC has a warning in their header. *sigh*. */
5 #if defined(__GNUC__) || defined(__clang__)
6  #pragma GCC diagnostic push
7  #pragma GCC diagnostic ignored "-Wpedantic"
8  #if defined(__clang__)
9  #pragma GCC diagnostic ignored "-Wc99-extensions"
10  #endif
11 #endif
12 #include <FLAC/stream_decoder.h>
13 #if defined(__GNUC__)
14  #pragma GCC diagnostic pop
15 #endif
16 
17 #include "../common/dr_common.c"
18 
19 
20 /*
21 The libflac object is used to make it easier to compare things against the reference implementation. I don't think
22 libFLAC's API is all that easy to use or intuitive so I'm wrapping it. This is deliberately simple. It decodes the
23 entire file into memory upon initialization.
24 */
25 typedef struct
26 {
27  drflac_int32* pPCMFrames; /* Interleaved. */
29  drflac_uint64 pcmFrameCap; /* The capacity of the pPCMFrames buffer in PCM frames. */
32  drflac_uint64 currentPCMFrame; /* The index of the PCM frame the decoder is currently sitting on. */
33  double decodeTimeInSeconds; /* The total amount of time it took to decode the file. This is used for profiling. */
36  size_t fileReadPos;
37 } libflac;
38 
39 static FLAC__StreamDecoderReadStatus libflac__read_callback(const FLAC__StreamDecoder *pStreamDecoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
40 {
41  libflac* pDecoder = (libflac*)client_data;
42  size_t bytesToRead = *bytes;
43  size_t bytesRemaining = pDecoder->fileSizeInBytes - pDecoder->fileReadPos;
44 
45  (void)pStreamDecoder;
46 
47  if (bytesToRead > bytesRemaining) {
48  bytesToRead = bytesRemaining;
49  }
50 
51  if (bytesToRead > 0) {
52  memcpy(buffer, pDecoder->pFileData + pDecoder->fileReadPos, bytesToRead);
53  pDecoder->fileReadPos += bytesToRead;
54  }
55 
56  *bytes = bytesToRead;
57  return (bytesToRead == 0 && bytesRemaining == 0) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
58 }
59 
60 static FLAC__StreamDecoderWriteStatus libflac__write_callback(const FLAC__StreamDecoder *pStreamDecoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
61 {
62  libflac* pDecoder = (libflac*)client_data;
63  drflac_uint32 pcmFramesInFLACFrame;
64  drflac_int32* pNextSampleInNewFrame;
65  drflac_uint32 i, j;
66 
67  (void)pStreamDecoder;
68 
69  pcmFramesInFLACFrame = frame->header.blocksize;
70 
71  /* Make sure there's room in the buffer. */
72  if ((pDecoder->pcmFrameCount + pcmFramesInFLACFrame) > pDecoder->pcmFrameCap) {
73  drflac_int32* pNewPCMFrames;
74 
75  pDecoder->pcmFrameCap *= 2;
76  if (pDecoder->pcmFrameCap < (pDecoder->pcmFrameCount + pcmFramesInFLACFrame)) {
77  pDecoder->pcmFrameCap = (pDecoder->pcmFrameCount + pcmFramesInFLACFrame);
78  }
79 
80  pNewPCMFrames = (drflac_int32*)realloc(pDecoder->pPCMFrames, (size_t)(pDecoder->pcmFrameCap * pDecoder->channels * sizeof(drflac_int32)));
81  if (pNewPCMFrames == NULL) {
82  return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
83  }
84 
85  pDecoder->pPCMFrames = pNewPCMFrames;
86  }
87 
88  /* Make sure the decoded samples are interleaved. */
89  pNextSampleInNewFrame = pDecoder->pPCMFrames + (pDecoder->pcmFrameCount * pDecoder->channels);
90  for (i = 0; i < pcmFramesInFLACFrame; i += 1) {
91  for (j = 0; j < pDecoder->channels; ++j) {
92  *pNextSampleInNewFrame++ = buffer[j][i] << (32 - frame->header.bits_per_sample);
93  }
94  }
95 
96  pDecoder->pcmFrameCount += pcmFramesInFLACFrame;
97 
98  return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
99 }
100 
101 static FLAC__StreamDecoderLengthStatus libflac__length_callback(const FLAC__StreamDecoder *pStreamDecoder, FLAC__uint64 *stream_length, void *client_data)
102 {
103  libflac* pDecoder = (libflac*)client_data;
104 
105  (void)pStreamDecoder;
106 
107  *stream_length = pDecoder->fileSizeInBytes;
108  return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
109 }
110 
111 static void libflac__metadata_callback(const FLAC__StreamDecoder *pStreamDecoder, const FLAC__StreamMetadata *metadata, void *client_data)
112 {
113  libflac* pDecoder = (libflac*)client_data;
114 
115  (void)pStreamDecoder;
116 
117  /* Here is where we initialize the buffer for the decoded data. */
118  if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
119  pDecoder->pcmFrameCount = 0; /* Always set this to 0. Don't be tempted to set it to metadata->data.stream_info.total_samples. It's increment in libflac__write_callback. */
120  pDecoder->channels = metadata->data.stream_info.channels;
121  pDecoder->sampleRate = metadata->data.stream_info.sample_rate;
122 
123  /* Allocate an initial block of memory if we know the total size. */
124  if (metadata->data.stream_info.total_samples > 0) {
125  pDecoder->pcmFrameCap = metadata->data.stream_info.total_samples;
126  pDecoder->pPCMFrames = (drflac_int32*)malloc((size_t)(pDecoder->pcmFrameCap * pDecoder->channels * sizeof(drflac_int32)));
127  if (pDecoder->pPCMFrames != NULL) {
128  DRFLAC_ZERO_MEMORY(pDecoder->pPCMFrames, (size_t)(pDecoder->pcmFrameCap * pDecoder->channels * sizeof(drflac_int32)));
129  }
130  }
131  }
132 }
133 
134 static void libflac__error_callback(const FLAC__StreamDecoder *pStreamDecoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
135 {
136  (void)pStreamDecoder;
137  (void)status;
138  (void)client_data;
139 }
140 
141 /*
142 Initializes a libflac object.
143 
144 This will perform a full decode of the file using libFLAC. The time it takes to decode the file will be stored in decodeTimeInSeconds
145 for the purpose of profiling. The decoding process will load the entire file into memory before calling into libFLAC. This way profiling
146 will exclude any IO time.
147 */
148 drflac_result libflac_init_file(const char* pFilePath, libflac* pDecoder)
149 {
150  FLAC__StreamDecoder* pStreamDecoder;
151  FLAC__bool libflacResult;
152  FLAC__StreamDecoderInitStatus libflacStatus;
153  double decodeTimeBeg;
154  double decodeTimeEnd;
155 
156  DRFLAC_ZERO_MEMORY(pDecoder, sizeof(*pDecoder));
157 
158  pDecoder->pFileData = (drflac_uint8*)dr_open_and_read_file(pFilePath, &pDecoder->fileSizeInBytes);
159  if (pDecoder->pFileData == NULL) {
160  return DRFLAC_ERROR; /* Failed to open the file. */
161  }
162 
163 
164  /* Initialize the libFLAC decoder. */
165  pStreamDecoder = FLAC__stream_decoder_new();
166  if (pDecoder == NULL) {
167  return DRFLAC_ERROR; /* Failed to create a new stream decoder. Out of memory. */
168  }
169 
170  if (dr_extension_equal(pFilePath, "ogg") || dr_extension_equal(pFilePath, "oga") || dr_extension_equal(pFilePath, "ogv")) {
171  libflacStatus = FLAC__stream_decoder_init_ogg_stream(pStreamDecoder, libflac__read_callback, NULL, NULL, libflac__length_callback, NULL, libflac__write_callback, libflac__metadata_callback, libflac__error_callback, pDecoder);
172  } else {
173  libflacStatus = FLAC__stream_decoder_init_stream(pStreamDecoder, libflac__read_callback, NULL, NULL, libflac__length_callback, NULL, libflac__write_callback, libflac__metadata_callback, libflac__error_callback, pDecoder);
174  }
175 
176  if (libflacStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
177  FLAC__stream_decoder_delete(pStreamDecoder);
178  free(pDecoder->pFileData);
179  return DRFLAC_ERROR; /* Failed to initialize the stream. */
180  }
181 
182  /* Read past the metadata first. This will fire the libflac__metadata_callback which will do a bit of initialization for us. */
183  libflacResult = FLAC__stream_decoder_process_until_end_of_metadata(pStreamDecoder);
184  if (libflacResult == DRFLAC_FALSE) {
185  FLAC__stream_decoder_delete(pStreamDecoder);
186  free(pDecoder->pFileData);
187  return DRFLAC_ERROR; /* Failed to read metadata from the FLAC stream. */
188  }
189 
190  /* Now we can just decode the entire file. */
191  decodeTimeBeg = dr_timer_now();
192  libflacResult = FLAC__stream_decoder_process_until_end_of_stream(pStreamDecoder);
193  decodeTimeEnd = dr_timer_now();
194 
195  pDecoder->decodeTimeInSeconds = decodeTimeEnd - decodeTimeBeg;
196 
197  /* We're done with the libFLAC decoder. */
198  FLAC__stream_decoder_delete(pStreamDecoder);
199  pStreamDecoder = NULL;
200 
201 
202  /* Free the file data. */
203  free(pDecoder->pFileData);
204  pDecoder->pFileData = NULL;
205  pDecoder->fileSizeInBytes = 0;
206  pDecoder->fileReadPos = 0;
207 
208  if (libflacResult == DRFLAC_FALSE) {
209  return DRFLAC_ERROR; /* Some error ocurred while decoding. */
210  }
211 
212  return DRFLAC_SUCCESS;
213 }
214 
215 void libflac_uninit(libflac* pDecoder)
216 {
217  if (pDecoder == NULL) {
218  return;
219  }
220 
221  free(pDecoder->pPCMFrames);
222 }
223 
225 {
226  drflac_uint64 pcmFramesRemaining;
227 
228  if (pDecoder == NULL) {
229  return 0;
230  }
231 
232  pcmFramesRemaining = pDecoder->pcmFrameCount - pDecoder->currentPCMFrame;
233  if (framesToRead > pcmFramesRemaining) {
234  framesToRead = pcmFramesRemaining;
235  }
236 
237  if (framesToRead == 0) {
238  return 0;
239  }
240 
241  DRFLAC_COPY_MEMORY(pBufferOut, pDecoder->pPCMFrames + (pDecoder->currentPCMFrame * pDecoder->channels), (size_t)(framesToRead * pDecoder->channels * sizeof(drflac_int32)));
242  pDecoder->currentPCMFrame += framesToRead;
243 
244  return framesToRead;
245 }
246 
247 drflac_uint64 libflac_read_pcm_frames_f32(libflac* pDecoder, drflac_uint64 framesToRead, float* pBufferOut)
248 {
249  drflac_uint64 pcmFramesRemaining;
250 
251  if (pDecoder == NULL) {
252  return 0;
253  }
254 
255  pcmFramesRemaining = pDecoder->pcmFrameCount - pDecoder->currentPCMFrame;
256  if (framesToRead > pcmFramesRemaining) {
257  framesToRead = pcmFramesRemaining;
258  }
259 
260  if (framesToRead == 0) {
261  return 0;
262  }
263 
264  /* s32 to f32 */
265  dr_pcm_s32_to_f32(pBufferOut, pDecoder->pPCMFrames + (pDecoder->currentPCMFrame * pDecoder->channels), framesToRead * pDecoder->channels);
266  pDecoder->currentPCMFrame += framesToRead;
267 
268  return framesToRead;
269 }
270 
272 {
273  drflac_uint64 pcmFramesRemaining;
274 
275  if (pDecoder == NULL) {
276  return 0;
277  }
278 
279  pcmFramesRemaining = pDecoder->pcmFrameCount - pDecoder->currentPCMFrame;
280  if (framesToRead > pcmFramesRemaining) {
281  framesToRead = pcmFramesRemaining;
282  }
283 
284  if (framesToRead == 0) {
285  return 0;
286  }
287 
288  /* s32 to f32 */
289  dr_pcm_s32_to_s16(pBufferOut, pDecoder->pPCMFrames + (pDecoder->currentPCMFrame * pDecoder->channels), framesToRead * pDecoder->channels);
290  pDecoder->currentPCMFrame += framesToRead;
291 
292  return framesToRead;
293 }
294 
296 {
297  if (pDecoder == NULL) {
298  return DRFLAC_FALSE;
299  }
300 
301  if (targetPCMFrameIndex > pDecoder->pcmFrameCount) {
302  return DRFLAC_FALSE; /* Trying to seek too far forward. */
303  }
304 
305  pDecoder->currentPCMFrame = targetPCMFrameIndex;
306 
307  return DRFLAC_TRUE;
308 }
309 
310 
311 /* Helper for printing CPU caps from dr_flac. */
313 {
314 #if defined(DRFLAC_64BIT)
315  printf("64 Bit\n");
316 #else
317  printf("32 Bit\n");
318 #endif
319 
321 
322 #if defined(DRFLAC_X86) || defined(DRFLAC_X64)
323  #if defined(DRFLAC_X64)
324  printf("Architecture: x64\n");
325  #else
326  printf("Architecture: x86\n");
327  #endif
328  printf("Has SSE2: %s\n", drflac_has_sse2() ? "YES" : "NO");
329  printf("Has SSE4.1: %s\n", drflac_has_sse41() ? "YES" : "NO");
330  printf("Has LZCNT: %s\n", drflac__is_lzcnt_supported() ? "YES" : "NO");
331 #endif
332 }
DRFLAC_ZERO_MEMORY
#define DRFLAC_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51350
libflac::pcmFrameCount
drflac_uint64 pcmFrameCount
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:28
libflac__write_callback
static FLAC__StreamDecoderWriteStatus libflac__write_callback(const FLAC__StreamDecoder *pStreamDecoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:60
drflac_uint64
unsigned long long drflac_uint64
Definition: porcupine/demo/c/dr_libs/dr_flac.h:259
NULL
#define NULL
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:92
dr_extension_equal
dr_bool32 dr_extension_equal(const char *path, const char *extension)
Definition: porcupine/demo/c/dr_libs/tests/common/dr_common.c:343
libflac_read_pcm_frames_s16
drflac_uint64 libflac_read_pcm_frames_s16(libflac *pDecoder, drflac_uint64 framesToRead, drflac_int16 *pBufferOut)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:271
DRFLAC_COPY_MEMORY
#define DRFLAC_COPY_MEMORY(dst, src, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51347
drflac_uint8
unsigned char drflac_uint8
Definition: porcupine/demo/c/dr_libs/dr_flac.h:242
libflac__length_callback
static FLAC__StreamDecoderLengthStatus libflac__length_callback(const FLAC__StreamDecoder *pStreamDecoder, FLAC__uint64 *stream_length, void *client_data)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:101
libflac__read_callback
static FLAC__StreamDecoderReadStatus libflac__read_callback(const FLAC__StreamDecoder *pStreamDecoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:39
libflac_init_file
drflac_result libflac_init_file(const char *pFilePath, libflac *pDecoder)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:148
libflac::fileReadPos
size_t fileReadPos
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:36
libflac_seek_to_pcm_frame
drflac_bool32 libflac_seek_to_pcm_frame(libflac *pDecoder, drflac_uint64 targetPCMFrameIndex)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:295
drflac_has_sse41
static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51252
libflac__error_callback
static void libflac__error_callback(const FLAC__StreamDecoder *pStreamDecoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:134
dr_pcm_s32_to_s16
void dr_pcm_s32_to_s16(void *dst, const void *src, dr_uint64 count)
Definition: porcupine/demo/c/dr_libs/tests/common/dr_common.c:901
libflac_read_pcm_frames_f32
drflac_uint64 libflac_read_pcm_frames_f32(libflac *pDecoder, drflac_uint64 framesToRead, float *pBufferOut)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:247
DRFLAC_ERROR
#define DRFLAC_ERROR
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51358
dr_open_and_read_file
void * dr_open_and_read_file(const char *filePath, size_t *pFileSizeOut)
Definition: porcupine/demo/c/dr_libs/tests/common/dr_common.c:675
dr_timer_now
double dr_timer_now()
Definition: porcupine/demo/c/dr_libs/tests/common/dr_common.c:800
drflac__init_cpu_caps
static DRFLAC_NO_THREAD_SANITIZE void drflac__init_cpu_caps(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51487
libflac
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:25
DRFLAC_FALSE
#define DRFLAC_FALSE
Definition: porcupine/demo/c/dr_libs/dr_flac.h:272
drflac_has_sse2
static DRFLAC_INLINE drflac_bool32 drflac_has_sse2(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51228
libflac::sampleRate
drflac_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:31
drflac_int16
signed short drflac_int16
Definition: porcupine/demo/c/dr_libs/dr_flac.h:243
libflac::pcmFrameCap
drflac_uint64 pcmFrameCap
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:29
libflac::pFileData
drflac_uint8 * pFileData
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:34
libflac::decodeTimeInSeconds
double decodeTimeInSeconds
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:33
libflac::channels
drflac_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:30
libflac__metadata_callback
static void libflac__metadata_callback(const FLAC__StreamDecoder *pStreamDecoder, const FLAC__StreamMetadata *metadata, void *client_data)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:111
drflac_bool32
drflac_uint32 drflac_bool32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:270
libflac::pPCMFrames
drflac_int32 * pPCMFrames
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:27
DRFLAC_TRUE
#define DRFLAC_TRUE
Definition: porcupine/demo/c/dr_libs/dr_flac.h:271
libflac_uninit
void libflac_uninit(libflac *pDecoder)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:215
drflac_uint32
unsigned int drflac_uint32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:246
print_cpu_caps
void print_cpu_caps()
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:312
libflac::fileSizeInBytes
size_t fileSizeInBytes
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:35
dr_pcm_s32_to_f32
void dr_pcm_s32_to_f32(void *dst, const void *src, dr_uint64 count)
Definition: porcupine/demo/c/dr_libs/tests/common/dr_common.c:880
DRFLAC_SUCCESS
#define DRFLAC_SUCCESS
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51357
drflac_int32
signed int drflac_int32
Definition: porcupine/demo/c/dr_libs/dr_flac.h:245
libflac_read_pcm_frames_s32
drflac_uint64 libflac_read_pcm_frames_s32(libflac *pDecoder, drflac_uint64 framesToRead, drflac_int32 *pBufferOut)
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:224
drflac_result
drflac_int32 drflac_result
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:51356
libflac::currentPCMFrame
drflac_uint64 currentPCMFrame
Definition: porcupine/demo/c/dr_libs/tests/flac/dr_flac_common.c:32


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:13:52