rhino/demo/c/dr_libs/wip/dr_opus.h
Go to the documentation of this file.
1 /*
2 Opus audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
3 dr_opus - v0.0.0 (Unreleased) - xxxx-xx-xx
4 
5 David Reid - mackron@gmail.com
6 */
7 
8 /* ====== WORK-IN-PROGRESSS ====== */
9 
10 #ifndef dr_opus_h
11 #define dr_opus_h
12 
13 #include <stddef.h> /* For size_t. */
14 
15 /* Sized types. Prefer built-in types. Fall back to stdint. */
16 #ifdef _MSC_VER
17  #if defined(__clang__)
18  #pragma GCC diagnostic push
19  #pragma GCC diagnostic ignored "-Wlanguage-extension-token"
20  #pragma GCC diagnostic ignored "-Wlong-long"
21  #pragma GCC diagnostic ignored "-Wc++11-long-long"
22  #endif
23  typedef signed __int8 dropus_int8;
24  typedef unsigned __int8 dropus_uint8;
25  typedef signed __int16 dropus_int16;
26  typedef unsigned __int16 dropus_uint16;
27  typedef signed __int32 dropus_int32;
28  typedef unsigned __int32 dropus_uint32;
29  typedef signed __int64 dropus_int64;
30  typedef unsigned __int64 dropus_uint64;
31  #if defined(__clang__)
32  #pragma GCC diagnostic pop
33  #endif
34 
35  #if defined(_WIN32)
36  #if defined(_WIN64)
38  #else
40  #endif
41  #elif defined(__GNUC__)
42  #if defined(__LP64__)
44  #else
46  #endif
47  #else
48  typedef dropus_uint64 dropus_uintptr; /* Fallback. */
49  #endif
50 #else
51  #include <stdint.h>
52  typedef int8_t dropus_int8;
53  typedef uint8_t dropus_uint8;
54  typedef int16_t dropus_int16;
55  typedef uint16_t dropus_uint16;
56  typedef int32_t dropus_int32;
57  typedef uint32_t dropus_uint32;
58  typedef int64_t dropus_int64;
59  typedef uint64_t dropus_uint64;
60  typedef uintptr_t dropus_uintptr;
61 #endif
64 #define DROPUS_TRUE 1
65 #define DROPUS_FALSE 0
66 
67 typedef void* dropus_handle;
68 typedef void* dropus_ptr;
69 typedef void (* dropus_proc)(void);
70 
71 #ifndef NULL
72 #define NULL 0
73 #endif
74 
75 #if defined(SIZE_MAX)
76  #define DROPUS_SIZE_MAX SIZE_MAX
77 #else
78  #define DROPUS_SIZE_MAX 0xFFFFFFFF /* When SIZE_MAX is not defined by the standard library just default to the maximum 32-bit unsigned integer. */
79 #endif
80 
81 #ifdef _MSC_VER
82  #define DROPUS_INLINE __forceinline
83 #elif defined(__GNUC__)
84  /*
85  I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
86  the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
87  case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
88  command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
89  I am using "__inline__" only when we're compiling in strict ANSI mode.
90  */
91  #if defined(__STRICT_ANSI__)
92  #define DROPUS_INLINE __inline__ __attribute__((always_inline))
93  #else
94  #define DROPUS_INLINE inline __attribute__((always_inline))
95  #endif
96 #else
97  #define DROPUS_INLINE
98 #endif
99 
100 #if !defined(DROPUS_API)
101  #if defined(DROPUS_DLL)
102  #if defined(_WIN32)
103  #define DROPUS_DLL_IMPORT __declspec(dllimport)
104  #define DROPUS_DLL_EXPORT __declspec(dllexport)
105  #define DROPUS_DLL_PRIVATE static
106  #else
107  #if defined(__GNUC__) && __GNUC__ >= 4
108  #define DROPUS_DLL_IMPORT __attribute__((visibility("default")))
109  #define DROPUS_DLL_EXPORT __attribute__((visibility("default")))
110  #define DROPUS_DLL_PRIVATE __attribute__((visibility("hidden")))
111  #else
112  #define DROPUS_DLL_IMPORT
113  #define DROPUS_DLL_EXPORT
114  #define DROPUS_DLL_PRIVATE static
115  #endif
116  #endif
117 
118  #if defined(DR_OPUS_IMPLEMENTATION) || defined(DROPUS_IMPLEMENTATION)
119  #define DROPUS_API DROPUS_DLL_EXPORT
120  #else
121  #define DROPUS_API DROPUS_DLL_IMPORT
122  #endif
123  #define DROPUS_PRIVATE DROPUS_DLL_PRIVATE
124  #else
125  #define DROPUS_API extern
126  #define DROPUS_PRIVATE static
127  #endif
128 #endif
129 
130 typedef int dropus_result;
131 #define DROPUS_SUCCESS 0
132 #define DROPUS_ERROR -1 /* A generic error. */
133 #define DROPUS_INVALID_ARGS -2
134 #define DROPUS_INVALID_OPERATION -3
135 #define DROPUS_OUT_OF_MEMORY -4
136 #define DROPUS_OUT_OF_RANGE -5
137 #define DROPUS_ACCESS_DENIED -6
138 #define DROPUS_DOES_NOT_EXIST -7
139 #define DROPUS_ALREADY_EXISTS -8
140 #define DROPUS_TOO_MANY_OPEN_FILES -9
141 #define DROPUS_INVALID_FILE -10
142 #define DROPUS_TOO_BIG -11
143 #define DROPUS_PATH_TOO_LONG -12
144 #define DROPUS_NAME_TOO_LONG -13
145 #define DROPUS_NOT_DIRECTORY -14
146 #define DROPUS_IS_DIRECTORY -15
147 #define DROPUS_DIRECTORY_NOT_EMPTY -16
148 #define DROPUS_END_OF_FILE -17
149 #define DROPUS_NO_SPACE -18
150 #define DROPUS_BUSY -19
151 #define DROPUS_IO_ERROR -20
152 #define DROPUS_INTERRUPT -21
153 #define DROPUS_UNAVAILABLE -22
154 #define DROPUS_ALREADY_IN_USE -23
155 #define DROPUS_BAD_ADDRESS -24
156 #define DROPUS_BAD_SEEK -25
157 #define DROPUS_BAD_PIPE -26
158 #define DROPUS_DEADLOCK -27
159 #define DROPUS_TOO_MANY_LINKS -28
160 #define DROPUS_NOT_IMPLEMENTED -29
161 #define DROPUS_NO_MESSAGE -30
162 #define DROPUS_BAD_MESSAGE -31
163 #define DROPUS_NO_DATA_AVAILABLE -32
164 #define DROPUS_INVALID_DATA -33
165 #define DROPUS_TIMEOUT -34
166 #define DROPUS_NO_NETWORK -35
167 #define DROPUS_NOT_UNIQUE -36
168 #define DROPUS_NOT_SOCKET -37
169 #define DROPUS_NO_ADDRESS -38
170 #define DROPUS_BAD_PROTOCOL -39
171 #define DROPUS_PROTOCOL_UNAVAILABLE -40
172 #define DROPUS_PROTOCOL_NOT_SUPPORTED -41
173 #define DROPUS_PROTOCOL_FAMILY_NOT_SUPPORTED -42
174 #define DROPUS_ADDRESS_FAMILY_NOT_SUPPORTED -43
175 #define DROPUS_SOCKET_NOT_SUPPORTED -44
176 #define DROPUS_CONNECTION_RESET -45
177 #define DROPUS_ALREADY_CONNECTED -46
178 #define DROPUS_NOT_CONNECTED -47
179 #define DROPUS_CONNECTION_REFUSED -48
180 #define DROPUS_NO_HOST -49
181 #define DROPUS_IN_PROGRESS -50
182 #define DROPUS_CANCELLED -51
183 #define DROPUS_MEMORY_ALREADY_MAPPED -52
184 #define DROPUS_AT_END -53
185 #define DROPUS_CRC_MISMATCH -100
186 #define DROPUS_BAD_DATA -101
187 
188 /***********************************************************************************************************************************************************
189 
190 Low-Level Opus Stream API
191 
192 This API is where the low-level decoding takes place. In order to use this, you must know the packet structure of the Opus stream. This is usually the job of
193 encapsulations such as Ogg and Matroska.
194 
195 ************************************************************************************************************************************************************/
196 #define DROPUS_MAX_OPUS_FRAMES_PER_PACKET 48 /* RFC 6716 - Section 3.2.5 */
197 #define DROPUS_MAX_PCM_FRAMES_PER_PACKET 6144 /* RFC 6716 - Section 3.2.5. Maximum of 120ms. Maximum rate is 48kHz. 6144 = 120*48. */
198 
199 typedef enum
200 {
204 } dropus_mode;
205 
206 typedef struct
207 {
208  dropus_uint16 sizeInBytes;
210 
211 typedef struct
212 {
213  dropus_uint8 toc; /* TOC byte. RFC 6716 - Section 3.1 */
216 
217 typedef struct
218 {
219  dropus_stream_packet packet; /* The current packet. */
220  struct
221  {
222  dropus_int32 w0_Q13_prev; /* Previous stereo weights. */
223  dropus_int32 w1_Q13_prev;
224  } silk;
225 } dropus_stream;
226 
227 /*
228 Initializes a new low-level Opus stream object.
229 */
231 
232 /*
233 Decodes a packet from raw compressed data.
234 */
235 DROPUS_API dropus_result dropus_stream_decode_packet(dropus_stream* pOpusStream, const void* pData, size_t dataSize);
236 
237 
238 
239 /***********************************************************************************************************************************************************
240 
241 High-Level Opus Decoding API
242 
243 ************************************************************************************************************************************************************/
244 typedef enum
245 {
249 
250 typedef size_t (* dropus_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
251 typedef dropus_bool32 (* dropus_seek_proc)(void* pUserData, int offset, dropus_seek_origin origin);
252 
253 typedef struct
254 {
255  void* pUserData;
256  void* (* onMalloc)(size_t sz, void* pUserData);
257  void* (* onRealloc)(void* p, size_t sz, void* pUserData);
258  void (* onFree)(void* p, void* pUserData);
260 
261 typedef struct
262 {
263  dropus_read_proc onRead;
264  dropus_seek_proc onSeek;
265  void* pUserData;
266  dropus_allocation_callbacks allocationCallbacks;
267  void* pFile; /* Only used for decoders that were opened against a file. */
268  struct
269  {
270  const dropus_uint8* pData;
271  size_t dataSize;
272  size_t currentReadPos;
273  } memory; /* Only used for decoders that were opened against a block of memory. */
274 } dropus;
275 
276 /*
277 Initializes a pre-allocated decoder object from callbacks.
278 */
279 DROPUS_API dropus_result dropus_init(dropus* pOpus, dropus_read_proc onRead, dropus_seek_proc onSeek, void* pUserData, const dropus_allocation_callbacks* pAllocationCallbacks);
280 
281 #ifndef DR_OPUS_NO_STDIO
282 /*
283 Initializes a pre-allocated decoder object from a file.
284 
285 This keeps hold of the file handle throughout the lifetime of the decoder and closes it in dropus_uninit().
286 */
287 DROPUS_API dropus_result dropus_init_file(dropus* pOpus, const char* pFilePath, const dropus_allocation_callbacks* pAllocationCallbacks);
288 DROPUS_API dropus_result dropus_init_file_w(dropus* pOpus, const wchar_t* pFilePath, const dropus_allocation_callbacks* pAllocationCallbacks);
289 #endif
290 
291 /*
292 Initializes a pre-allocated decoder object from a block of memory.
293 
294 This does not make a copy of the memory.
295 */
296 DROPUS_API dropus_result dropus_init_memory(dropus* pOpus, const void* pData, size_t dataSize, const dropus_allocation_callbacks* pAllocationCallbacks);
297 
298 /*
299 Uninitializes an Opus decoder.
300 */
301 DROPUS_API void dropus_uninit(dropus* pOpus);
302 
303 
304 
305 /************************************************************************************************************************************************************
306 
307 Utilities
308 
309 ************************************************************************************************************************************************************/
310 /*
311 Retrieves a human readable description of the given result code.
312 */
314 
315 /*
316 Allocates memory from callbacks.
317 
318 
319 Parameters
320 ----------
321 sz (in)
322  The size of the allocation in bytes.
323 
324 pAllocationCallbacks (in, optional)
325  A pointer to the `dropus_allocation_callbacks` object containing pointers to the allocation routines.
326 
327 
328 Return Value
329 ------------
330 A pointer to the allocated block of memory. NULL if an error occurs.
331 
332 
333 Remarks
334 -------
335 `pAllocationCallbacks` can be NULL, in which case DROPUS_MALLOC() will be used. Otherwise, if `pAllocationCallbacks` is not null, either `onMalloc` or
336 `onRealloc` must be set. If `onMalloc` is NULL, it will fall back to `onRealloc`. If both `onMalloc` and `onRealloc` are NULL, NULL will be returned.
337 */
338 DROPUS_API void* dropus_malloc(size_t sz, const dropus_allocation_callbacks* pAllocationCallbacks);
339 
340 /*
341 Reallocates memory from callbacks.
342 
343 
344 Parameters
345 ----------
346 p (in)
347  A pointer to the memory being reallocated.
348 
349 sz (in)
350  The size of the allocation in bytes.
351 
352 pAllocationCallbacks (in, optional)
353  A pointer to the `dropus_allocation_callbacks` object containing pointers to the allocation routines.
354 
355 
356 Return Value
357 ------------
358 A pointer to the allocated block of memory. NULL if an error occurs.
359 
360 
361 Remarks
362 -------
363 `pAllocationCallbacks` can be NULL, in which case DROPUS_REALLOC() will be used. If `onRealloc` is NULL, this will fail and NULL will be returned.
364 */
365 DROPUS_API void* dropus_realloc(void* p, size_t sz, const dropus_allocation_callbacks* pAllocationCallbacks);
366 
367 /*
368 Frees memory allocated by `dropus_malloc()` or `dropus_realloc()`.
369 
370 
371 Parameters
372 ----------
373 p (in)
374  A pointer to the memory being freed.
375 
376 
377 Remarks
378 -------
379 `pAllocationCallbacks` can be NULL in which case DROPUS_FREE() will be used. If `onFree` is NULL, this will be a no-op.
380 */
381 DROPUS_API void dropus_free(void* p, const dropus_allocation_callbacks* pAllocationCallbacks);
382 
383 
384 #endif /* dr_opus_h */
385 
386 /************************************************************************************************************************************************************
387  ************************************************************************************************************************************************************
388 
389  IMPLEMENTATION
390 
391  ************************************************************************************************************************************************************
392  ************************************************************************************************************************************************************/
393 #if defined(DR_OPUS_IMPLEMENTATION) || defined(DROPUS_IMPLEMENTATION)
394 #include <stdlib.h>
395 #include <string.h>
396 #ifndef DR_OPUS_NO_STDIO
397 #include <stdio.h>
398 #include <wchar.h> /* For wcslen(), wcsrtombs() */
399 #endif
400 
401 /* CPU Architecture. */
402 #if defined(__x86_64__) || defined(_M_X64)
403  #define DROPUS_X64
404 #elif defined(__i386) || defined(_M_IX86)
405  #define DROPUS_X86
406 #elif defined(__arm__) || defined(_M_ARM)
407  #define DROPUS_ARM
408 #endif
409 
410 /* Compile-time CPU feature support. */
411 #if !defined(DR_OPUS_NO_SIMD) && (defined(DROPUS_X86) || defined(DROPUS_X64))
412  #if defined(_MSC_VER) && !defined(__clang__)
413  #if _MSC_VER >= 1400
414  #include <intrin.h>
415  static DROPUS_INLINE void dropus__cpuid(int info[4], int fid)
416  {
417  __cpuid(info, fid);
418  }
419  #else
420  #define DROPUS_NO_CPUID
421  #endif
422  #else
423  #if defined(__GNUC__) || defined(__clang__)
424  static DROPUS_INLINE void dropus__cpuid(int info[4], int fid)
425  {
426  /*
427  It looks like the -fPIC option uses the ebx register which GCC complains about. We can work around this by just using a different register, the
428  specific register of which I'm letting the compiler decide on. The "k" prefix is used to specify a 32-bit register. The {...} syntax is for
429  supporting different assembly dialects.
430 
431  What's basically happening is that we're saving and restoring the ebx register manually.
432  */
433  #if defined(DROPUS_X86) && defined(__PIC__)
434  __asm__ __volatile__ (
435  "xchg{l} {%%}ebx, %k1;"
436  "cpuid;"
437  "xchg{l} {%%}ebx, %k1;"
438  : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
439  );
440  #else
441  __asm__ __volatile__ (
442  "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
443  );
444  #endif
445  }
446  #else
447  #define DROPUS_NO_CPUID
448  #endif
449  #endif
450 #else
451  #define DROPUS_NO_CPUID
452 #endif
453 
454 
455 #if defined(_MSC_VER) && _MSC_VER >= 1500 && (defined(DROPUS_X86) || defined(DROPUS_X64))
456  #define DROPUS_HAS_LZCNT_INTRINSIC
457 #elif (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
458  #define DROPUS_HAS_LZCNT_INTRINSIC
459 #elif defined(__clang__)
460  #if __has_builtin(__builtin_clzll) || __has_builtin(__builtin_clzl)
461  #define DROPUS_HAS_LZCNT_INTRINSIC
462  #endif
463 #endif
464 
465 #if defined(_MSC_VER) && _MSC_VER >= 1400
466  #define DROPUS_HAS_BYTESWAP16_INTRINSIC
467  #define DROPUS_HAS_BYTESWAP32_INTRINSIC
468  #define DROPUS_HAS_BYTESWAP64_INTRINSIC
469 #elif defined(__clang__)
470  #if __has_builtin(__builtin_bswap16)
471  #define DROPUS_HAS_BYTESWAP16_INTRINSIC
472  #endif
473  #if __has_builtin(__builtin_bswap32)
474  #define DROPUS_HAS_BYTESWAP32_INTRINSIC
475  #endif
476  #if __has_builtin(__builtin_bswap64)
477  #define DROPUS_HAS_BYTESWAP64_INTRINSIC
478  #endif
479 #elif defined(__GNUC__)
480  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
481  #define DROPUS_HAS_BYTESWAP32_INTRINSIC
482  #define DROPUS_HAS_BYTESWAP64_INTRINSIC
483  #endif
484  #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
485  #define DROPUS_HAS_BYTESWAP16_INTRINSIC
486  #endif
487 #endif
488 
489 
490 #ifndef DROPUS_ASSERT
491 #include <assert.h>
492 #define DROPUS_ASSERT(expression) assert(expression)
493 #endif
494 #ifndef DROPUS_MALLOC
495 #define DROPUS_MALLOC(sz) malloc((sz))
496 #endif
497 #ifndef DROPUS_REALLOC
498 #define DROPUS_REALLOC(p, sz) realloc((p), (sz))
499 #endif
500 #ifndef DROPUS_FREE
501 #define DROPUS_FREE(p) free((p))
502 #endif
503 #ifndef DROPUS_COPY_MEMORY
504 #define DROPUS_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
505 #endif
506 #ifndef DROPUS_ZERO_MEMORY
507 #define DROPUS_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
508 #endif
509 #ifndef DROPUS_ZERO_OBJECT
510 #define DROPUS_ZERO_OBJECT(p) DROPUS_ZERO_MEMORY((p), sizeof(*(p)))
511 #endif
512 
513 #ifndef DROPUS_MIN
514 #define DROPUS_MIN(x, y) (((x) < (y)) ? (x) : (y))
515 #endif
516 #ifndef DROPUS_MAX
517 #define DROPUS_MAX(x, y) (((x) > (y)) ? (x) : (y))
518 #endif
519 #ifndef DROPUS_COUNTOF
520 #define DROPUS_COUNTOF(p) (sizeof(p) / sizeof((p)[0]))
521 #endif
522 
523 
524 /***********************************
525 Endian Management
526 ************************************/
527 static DROPUS_INLINE dropus_bool32 dropus__is_little_endian()
528 {
529 #if defined(DROPUS_X86) || defined(DROPUS_X64)
530  return DROPUS_TRUE;
531 #elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
532  return DROPUS_TRUE;
533 #else
534  int n = 1;
535  return (*(char*)&n) == 1;
536 #endif
537 }
538 
539 static DROPUS_INLINE dropus_uint16 dropus__swap_endian_uint16(dropus_uint16 n)
540 {
541 #ifdef DROPUS_HAS_BYTESWAP16_INTRINSIC
542  #if defined(_MSC_VER)
543  return _byteswap_ushort(n);
544  #elif defined(__GNUC__) || defined(__clang__)
545  return __builtin_bswap16(n);
546  #else
547  #error "This compiler does not support the byte swap intrinsic."
548  #endif
549 #else
550  return ((n & 0xFF00) >> 8) |
551  ((n & 0x00FF) << 8);
552 #endif
553 }
554 
555 static DROPUS_INLINE dropus_uint32 dropus__swap_endian_uint32(dropus_uint32 n)
556 {
557 #ifdef DROPUS_HAS_BYTESWAP32_INTRINSIC
558  #if defined(_MSC_VER)
559  return _byteswap_ulong(n);
560  #elif defined(__GNUC__) || defined(__clang__)
561  return __builtin_bswap32(n);
562  #else
563  #error "This compiler does not support the byte swap intrinsic."
564  #endif
565 #else
566  return ((n & 0xFF000000) >> 24) |
567  ((n & 0x00FF0000) >> 8) |
568  ((n & 0x0000FF00) << 8) |
569  ((n & 0x000000FF) << 24);
570 #endif
571 }
572 
573 static DROPUS_INLINE dropus_uint64 dropus__swap_endian_uint64(dropus_uint64 n)
574 {
575 #ifdef DROPUS_HAS_BYTESWAP64_INTRINSIC
576  #if defined(_MSC_VER)
577  return _byteswap_uint64(n);
578  #elif defined(__GNUC__) || defined(__clang__)
579  return __builtin_bswap64(n);
580  #else
581  #error "This compiler does not support the byte swap intrinsic."
582  #endif
583 #else
584  return ((n & (dropus_uint64)0xFF00000000000000) >> 56) |
585  ((n & (dropus_uint64)0x00FF000000000000) >> 40) |
586  ((n & (dropus_uint64)0x0000FF0000000000) >> 24) |
587  ((n & (dropus_uint64)0x000000FF00000000) >> 8) |
588  ((n & (dropus_uint64)0x00000000FF000000) << 8) |
589  ((n & (dropus_uint64)0x0000000000FF0000) << 24) |
590  ((n & (dropus_uint64)0x000000000000FF00) << 40) |
591  ((n & (dropus_uint64)0x00000000000000FF) << 56);
592 #endif
593 }
594 
595 
596 static DROPUS_INLINE dropus_uint16 dropus__be2host_16(dropus_uint16 n)
597 {
598  if (dropus__is_little_endian()) {
599  return dropus__swap_endian_uint16(n);
600  }
601 
602  return n;
603 }
604 
605 static DROPUS_INLINE dropus_uint32 dropus__be2host_32(dropus_uint32 n)
606 {
607  if (dropus__is_little_endian()) {
608  return dropus__swap_endian_uint32(n);
609  }
610 
611  return n;
612 }
613 
614 static DROPUS_INLINE dropus_uint64 dropus__be2host_64(dropus_uint64 n)
615 {
616  if (dropus__is_little_endian()) {
617  return dropus__swap_endian_uint64(n);
618  }
619 
620  return n;
621 }
622 
623 
624 static DROPUS_INLINE dropus_uint16 dropus__le2host_16(dropus_uint16 n)
625 {
626  if (!dropus__is_little_endian()) {
627  return dropus__swap_endian_uint16(n);
628  }
629 
630  return n;
631 }
632 
633 static DROPUS_INLINE dropus_uint32 dropus__le2host_32(dropus_uint32 n)
634 {
635  if (!dropus__is_little_endian()) {
636  return dropus__swap_endian_uint32(n);
637  }
638 
639  return n;
640 }
641 
642 static DROPUS_INLINE dropus_uint64 dropus__le2host_64(dropus_uint64 n)
643 {
644  if (!dropus__is_little_endian()) {
645  return dropus__swap_endian_uint64(n);
646  }
647 
648  return n;
649 }
650 
651 
652 /***********************************************************************************************************************************************************
653 
654 Low-Level Opus Stream API
655 
656 ************************************************************************************************************************************************************/
657 #define DROPUS_MAX_FRAME_SIZE_IN_BYTES 1275 /* RFC 6716 - Section 3.4 [R2] */
658 #define DROPUS_MAX_PACKET_SIZE_IN_BYTES DROPUS_MAX_FRAME_SIZE_IN_BYTES*DROPUS_MAX_OPUS_FRAMES_PER_PACKET
659 
660 /***********************************
661 RFC 6716 - Section 3.1 The TOC Byte
662 ************************************/
663 static DROPUS_INLINE dropus_uint8 dropus_toc_config(dropus_uint8 toc)
664 {
665  return (toc & 0xF8) >> 3;
666 }
667 
668 static DROPUS_INLINE dropus_uint8 dropus_toc_s(dropus_uint8 toc)
669 {
670  return (toc & 0x04) >> 2;
671 }
672 
673 static DROPUS_INLINE dropus_uint8 dropus_toc_c(dropus_uint8 toc)
674 {
675  return (toc & 0x03);
676 }
677 
678 static DROPUS_INLINE dropus_mode dropus_toc_config_mode(dropus_uint8 config)
679 {
680  /* Table 2 in RFC 6716 */
681  static dropus_mode modes[32] = {
685  dropus_mode_hybrid, dropus_mode_hybrid, /* 12...13 */
686  dropus_mode_hybrid, dropus_mode_hybrid, /* 14...15 */
691  };
692 
693  DROPUS_ASSERT(config < 32);
694  return modes[config];
695 }
696 
697 static DROPUS_INLINE dropus_mode dropus_toc_mode(dropus_uint8 toc)
698 {
699  return dropus_toc_config_mode(dropus_toc_config(toc));
700 }
701 
702 static DROPUS_INLINE dropus_uint32 dropus_toc_config_sample_rate(dropus_uint8 config)
703 {
704  /* Table 2 with Table 1 in RFC 6716 */
705  static dropus_uint32 rates[32] = {
706  8000, 8000, 8000, 8000, /* 0...3 */
707  12000, 12000, 12000, 12000, /* 4...7 */
708  16000, 16000, 16000, 16000, /* 8...11 */
709  24000, 24000, /* 12...13 */
710  48000, 48000, /* 14...15 */
711  8000, 8000, 8000, 8000, /* 16...19 */
712  16000, 16000, 16000, 16000, /* 20...23 */
713  24000, 24000, 24000, 24000, /* 24...27 */
714  48000, 48000, 48000, 48000 /* 28...31 */
715  };
716 
717  DROPUS_ASSERT(config < 32);
718  return rates[config];
719 }
720 
721 static DROPUS_INLINE dropus_uint32 dropus_toc_sample_rate(dropus_uint8 toc)
722 {
723  return dropus_toc_config_sample_rate(dropus_toc_config(toc));
724 }
725 
726 static DROPUS_INLINE dropus_uint32 dropus_toc_sample_rate_ms(dropus_uint8 toc)
727 {
728  return dropus_toc_sample_rate(toc) / 1000;
729 }
730 
731 static DROPUS_INLINE dropus_uint32 dropus_toc_config_frame_size_in_pcm_frames(dropus_uint8 config)
732 {
733  /* Table 2 with Table 1 in RFC 6716 */
734  static dropus_uint32 sizes[32] = {
735  80, 160, 320, 480, /* 0...3 */
736  120, 240, 480, 720, /* 4...7 */
737  160, 320, 640, 960, /* 8...11 */
738  240, 480, /* 12...13 */
739  480, 960, /* 14...15 */
740  20, 40, 80, 160, /* 16...19 */
741  40, 80, 160, 320, /* 20...23 */
742  60, 120, 240, 480, /* 24...27 */
743  120, 240, 480, 960 /* 28...31 */
744  };
745 
746  DROPUS_ASSERT(config < 32);
747  return sizes[config];
748 }
749 
750 static DROPUS_INLINE dropus_uint32 dropus_toc_frame_size_in_pcm_frames(dropus_uint8 toc)
751 {
752  return dropus_toc_config_frame_size_in_pcm_frames(dropus_toc_config(toc));
753 }
754 
755 static DROPUS_INLINE dropus_uint8 dropus_toc_config_silk_frame_count(dropus_uint8 config)
756 {
757  /* Table 2 in RFC 6716 */
758  static dropus_uint8 counts[32] = {
759  1, 1, 2, 3, /* 0...3 */
760  1, 1, 2, 3, /* 4...7 */
761  1, 1, 2, 3, /* 8...11 */
762  1, 1, /* 12...13 */
763  1, 1, /* 14...15 */
764  0, 0, 0, 0, /* 16...19 */ /* Here down is CELT-only. */
765  0, 0, 0, 0, /* 20...23 */
766  0, 0, 0, 0, /* 24...27 */
767  0, 0, 0, 0 /* 28...31 */
768  };
769 
770  DROPUS_ASSERT(config < 32);
771  return counts[config];
772 }
773 
774 static DROPUS_INLINE dropus_uint8 dropus_toc_silk_frame_count(dropus_uint8 toc)
775 {
776  return dropus_toc_config_silk_frame_count(dropus_toc_config(toc));
777 }
778 
779 static DROPUS_INLINE dropus_int32 dropus_Q13(dropus_uint16 index)
780 {
781  /* Table 7 in RFC 6716 */
782  static dropus_int32 Q13[16] = {
783  -13732, -10050, -8266, -7526,
784  -6500, -5000, -2950, -820,
785  820, 2950, 5000, 6500,
786  7526, 8266, 10050, 13732
787  };
788 
789  DROPUS_ASSERT(index < DROPUS_COUNTOF(Q13));
790  return Q13[index];
791 }
792 
793 
794 typedef struct
795 {
796  const dropus_uint8* pData;
797  dropus_uint16 dataSize;
798  dropus_uint16 readPointer;
799  dropus_uint8 b0;
800  dropus_uint32 rng; /* RFC 6716 - Section 4.1 - Both val and rng are 32-bit unsigned integer values. */
801  dropus_uint32 val; /* ^^^ */
802 } dropus_range_decoder;
803 
804 static DROPUS_INLINE void dropus_range_decoder_normalize(dropus_range_decoder* pRangeDecoder)
805 {
806  dropus_uint8 sym;
807  dropus_uint8 b1;
808 
809  DROPUS_ASSERT(pRangeDecoder != NULL);
810 
811  while (pRangeDecoder->rng <= 0x800000) {
812  pRangeDecoder->rng = (pRangeDecoder->rng << 8); /* RFC 6716 - Section 4.1.2.1 - First, it sets rng to (rng<<8). */
813 
814  /* RFC 6716 - Section 4.1.2.1 - If no more input bytes remain, it uses zero bits instead. */
815  if (pRangeDecoder->dataSize > pRangeDecoder->readPointer) {
816  b1 = pRangeDecoder->pData[pRangeDecoder->readPointer++];
817  } else {
818  b1 = 0;
819  }
820 
821  /* RFC 6716 - Section 4.1.2.1 - ... using the leftover bit buffered from the previous byte as the high bit and the top 7 bits of the byte just read as the other 7 bits of sym. */
822  sym = ((pRangeDecoder->b0 & 0x01) << 7) | (b1 >> 7);
823 
824  /* RFC 6716 - Section 4.1.2.1 - The remaining bit in the byte just read is buffered for use in the next iteration. */
825  pRangeDecoder->b0 = (b1 & 0x01);
826 
827  /* val */
828  pRangeDecoder->val = ((pRangeDecoder->val << 8) + (255 - sym)) & 0x7FFFFFFF;
829  }
830 
831  DROPUS_ASSERT(pRangeDecoder->rng > 0x800000);
832 }
833 
834 static DROPUS_INLINE void dropus_range_decoder_init(const dropus_uint8* pData, dropus_uint16 dataSize, dropus_range_decoder* pRangeDecoder)
835 {
836  DROPUS_ASSERT(pRangeDecoder != NULL);
837 
838  pRangeDecoder->pData = pData;
839  pRangeDecoder->dataSize = dataSize;
840  pRangeDecoder->readPointer = 0;
841 
842  pRangeDecoder->b0 = 0; /* RFC 6716 - Section 4.1.1 - Let b0 be an 8-bit unsigned integer containing first input byte (or containing zero if there are no bytes in this Opus frame). */
843  if (dataSize > 0) {
844  pRangeDecoder->b0 = pData[pRangeDecoder->readPointer++];
845  }
846 
847  pRangeDecoder->rng = 128; /* RFC 6716 - Section 4.1.1 - The decoder initializes rng to 128 ... */
848  pRangeDecoder->val = 127 - (pRangeDecoder->b0 >> 1); /* ... and initializes val to (127 - (b0>>1)) ...*/
849 
850  /*
851  It saves the remaining bit, (b0&1), for use in the renormalization
852  procedure described in Section 4.1.2.1, which the decoder invokes
853  immediately after initialization to read additional bits and
854  establish the invariant that rng > 2**23.
855  */
856  dropus_range_decoder_normalize(pRangeDecoder);
857 }
858 
859 static DROPUS_INLINE dropus_uint16 dropus_range_decoder_fs(dropus_range_decoder* pRangeDecoder, dropus_uint16 ft)
860 {
861  /* Implements RFC 6716 - Section 4.1.2 (first step) */
862 
863  DROPUS_ASSERT(pRangeDecoder != NULL);
864  /*DROPUS_ASSERT(ft <= 65535);*/ /* RFC 6716 - Section 4.1 */ /* Always true due to range limit of `ft`. */
865 
866  return (dropus_uint16)(ft - DROPUS_MIN((pRangeDecoder->val / (pRangeDecoder->rng/ft)) + 1, ft));
867 }
868 
869 static DROPUS_INLINE dropus_uint16 dropus_range_decoder_k(dropus_uint16* f, dropus_uint16 n, dropus_uint16 fs, dropus_uint16* flOut, dropus_uint16* fhOut)
870 {
871  dropus_uint8 i;
872  dropus_uint16 k = 0;
873  dropus_uint16 fl = 0;
874  dropus_uint16 fh = 0;
875  for (i = 0; i < n; ++i) {
876  fh = fl + f[i];
877  if (fl <= fs && fs < fh) {
878  k = i;
879  break;
880  }
881 
882  fl += f[i];
883  }
884 
885  *flOut = fl;
886  *fhOut = fh;
887  return k;
888 }
889 
890 static DROPUS_INLINE dropus_uint16 dropus_range_decoder_update(dropus_range_decoder* pRangeDecoder, dropus_uint16* f, dropus_uint16 n, dropus_uint16 ft, dropus_uint16 fs)
891 {
892  /* Implements RFC 6716 - Section 4.1.2 (second step) */
893  dropus_uint16 k;
894  dropus_uint16 fl;
895  dropus_uint16 fh;
896 
897  DROPUS_ASSERT(pRangeDecoder != NULL);
898  DROPUS_ASSERT(f != NULL);
899  DROPUS_ASSERT(n > 0);
900  DROPUS_ASSERT(ft > 0);
901 
902  k = dropus_range_decoder_k(f, n, fs, &fl, &fh);
903 
904  /*DROPUS_ASSERT(0 <= fl);*/ /* RFC 6716 - Section 4.1 */ /* Always true due to `fl` being unsigned. */
905  DROPUS_ASSERT(fl < fh); /* RFC 6716 - Section 4.1 */
906  DROPUS_ASSERT(fh <= ft); /* RFC 6716 - Section 4.1 */
907  /*DROPUS_ASSERT(ft <= 65535);*/ /* RFC 6716 - Section 4.1 */ /* Always true due to range limit of `ft`. */
908 
909  /* val */
910  pRangeDecoder->val = pRangeDecoder->val - (pRangeDecoder->rng/ft) * (ft - fh);
911 
912  /* rng */
913  if (fl > 0) { /* RFC 6716 - Section 4.1.2 - If fl[k] is greater than zero, then the decoder updates rng using... */
914  pRangeDecoder->rng = (pRangeDecoder->rng/ft) * (fh - fl);
915  } else { /* RFC 6716 - Section 4.1.2 - Otherwise, it updates rng using... */
916  pRangeDecoder->rng = pRangeDecoder->rng - (pRangeDecoder->rng/ft) * (ft - fh);
917  }
918 
919  /*
920  RFC 6716 - Section 4.1.2
921 
922  After the updates, implemented by ec_dec_update() (entdec.c), the
923  decoder normalizes the range using the procedure in the next section,
924  and returns the index k.
925  */
926  dropus_range_decoder_normalize(pRangeDecoder);
927 
928  return k;
929 }
930 
931 static DROPUS_INLINE dropus_uint16 dropus_range_decoder_decode(dropus_range_decoder* pRangeDecoder, dropus_uint16* f, dropus_uint16 n, dropus_uint16 ft)
932 {
933  dropus_uint16 fs;
934 
935  DROPUS_ASSERT(pRangeDecoder != NULL);
936  DROPUS_ASSERT(f != NULL);
937  DROPUS_ASSERT(n > 0);
938  DROPUS_ASSERT(ft > 0);
939 
940  /* Step 1 from RFC 6716 - Section 4.1.2. */
941  fs = dropus_range_decoder_fs(pRangeDecoder, ft);
942 
943  /* Step 2 from RFC 6716 - Section 4.1.2. */
944  return dropus_range_decoder_update(pRangeDecoder, f, n, ft, fs);
945 }
946 
947 
949 {
950  if (pOpusStream == NULL) {
951  return DROPUS_INVALID_ARGS;
952  }
953 
954  DROPUS_ZERO_OBJECT(pOpusStream);
955 
956  return DROPUS_SUCCESS;
957 }
958 
959 
960 #define DROPUS_MAX_SILK_FRAME_SIZE_IN_PCM_FRAMES 20*16 /* 20 = 20ms SILK frame length. 16 = Wideband sample rate. */
961 
962 
963 typedef enum
964 {
965  dropus_silk_frame_regularity_regular,
966  dropus_silk_frame_regularity_lbrr,
967 } dropus_silk_frame_regularity;
968 
969 typedef struct
970 {
971  union
972  {
973  dropus_int16 s16[DROPUS_MAX_SILK_FRAME_SIZE_IN_PCM_FRAMES];
974  float f32[DROPUS_MAX_SILK_FRAME_SIZE_IN_PCM_FRAMES];
975  } pcm;
976 } dropus_silk_frame;
977 
978 static dropus_result dropus_stream_decode_silk_frame(dropus_stream* pOpusStream, dropus_range_decoder* pRD, dropus_silk_frame_regularity regularity, dropus_uint8 iSILKFrame, dropus_uint8 iChannel, dropus_uint8* pFlagsVAD, dropus_uint8* pFlagsLBRR, dropus_silk_frame* pSILKFrame)
979 {
980  dropus_uint8 channels;
981  dropus_uint32 w0_Q13 = 0;
982  dropus_uint32 w1_Q13 = 0;
983  dropus_uint8 midOnlyFlag = 0;
984 
985  channels = dropus_toc_s(pOpusStream->packet.toc) + 1;
986 
987  /*
988  RFC 6716 - Section 4.2.7.1
989 
990  ... these weights are coded if and only if
991  - This is a stereo Opus frame (Section 3.1), and
992  - The current SILK frame corresponds to the mid channel.
993  */
994  if (channels == 2 && iChannel == 0) {
995  dropus_uint16 f_Stage1[] = {7, 2, 1, 1, 1, 10, 24, 8, 1, 1, 3, 23, 92, 23, 3, 1, 1, 8, 24, 10, 1, 1, 1, 2, 7}, ft_Stage1 = 256;
996  dropus_uint16 f_Stage2[] = {85, 86, 85}, ft_Stage2 = 256;
997  dropus_uint16 f_Stage3[] = {51, 51, 52, 51, 51}, ft_Stage3 = 256;
998  dropus_uint16 n;
999  dropus_uint16 i0, i1, i2, i3;
1000  dropus_uint16 wi0, wi1;
1001 
1002  n = dropus_range_decoder_decode(pRD, f_Stage1, DROPUS_COUNTOF(f_Stage1), ft_Stage1);
1003  i0 = dropus_range_decoder_decode(pRD, f_Stage2, DROPUS_COUNTOF(f_Stage2), ft_Stage2);
1004  i1 = dropus_range_decoder_decode(pRD, f_Stage3, DROPUS_COUNTOF(f_Stage3), ft_Stage3);
1005  i2 = dropus_range_decoder_decode(pRD, f_Stage2, DROPUS_COUNTOF(f_Stage2), ft_Stage2);
1006  i3 = dropus_range_decoder_decode(pRD, f_Stage3, DROPUS_COUNTOF(f_Stage3), ft_Stage3);
1007 
1008  wi0 = i0 + 3 * (n / 5);
1009  wi1 = i2 + 3 * (n % 5);
1010 
1011  /* Note that w0_Q13 depends on w1_Q13 so must be calculated afterwards. */
1012  w1_Q13 = dropus_Q13(wi1) + (((dropus_Q13((dropus_uint16)(wi1 + 1)) - dropus_Q13(wi1)) * 6554) >> 16) * ((2 * i3) + 1);
1013  w0_Q13 = dropus_Q13(wi0) + (((dropus_Q13((dropus_uint16)(wi0 + 1)) - dropus_Q13(wi0)) * 6554) >> 16) * ((2 * i1) + 1) - w1_Q13;
1014 
1015  /* RFC 6716 - Section 4.2.7.2 - Mid-Only Flag */
1016  {
1017  dropus_uint16 f_MOF[] = {192, 64}, ft_MOF = 256;
1018  midOnlyFlag = (dropus_uint8)dropus_range_decoder_decode(pRD, f_MOF, DROPUS_COUNTOF(f_MOF), ft_MOF);
1019  }
1020  }
1021 }
1022 
1023 static dropus_result dropus_stream_decode_silk_frame__mono(dropus_stream* pOpusStream, dropus_range_decoder* pRD, dropus_silk_frame_regularity regularity, dropus_uint8 iSILKFrame, dropus_uint8* pFlagsVAD, dropus_uint8* pFlagsLBRR, dropus_silk_frame* pSILKFrames)
1024 {
1025 
1026 }
1027 
1028 static dropus_result dropus_stream_decode_silk_frame__stereo(dropus_stream* pOpusStream, dropus_range_decoder* pRD, dropus_silk_frame_regularity regularity, dropus_uint8 iSILKFrame, dropus_uint8* pFlagsVAD, dropus_uint8* pFlagsLBRR, dropus_silk_frame* pSILKFrames)
1029 {
1030  dropus_uint8 iChannel;
1031  dropus_uint16 f_Stage1[] = {7, 2, 1, 1, 1, 10, 24, 8, 1, 1, 3, 23, 92, 23, 3, 1, 1, 8, 24, 10, 1, 1, 1, 2, 7}, ft_Stage1 = 256;
1032  dropus_uint16 f_Stage2[] = {85, 86, 85}, ft_Stage2 = 256;
1033  dropus_uint16 f_Stage3[] = {51, 51, 52, 51, 51}, ft_Stage3 = 256;
1034  dropus_uint16 n;
1035  dropus_uint16 i0, i1, i2, i3;
1036  dropus_uint16 wi0, wi1;
1037 
1038  /*
1039  RFC 6716 - Section 4.2.7.1
1040 
1041  ... these weights are coded if and only if
1042  - This is a stereo Opus frame (Section 3.1), and
1043  - The current SILK frame corresponds to the mid channel.
1044  */
1045 
1046  for (iChannel = 0; iChannel < 2; iChannel += 1) {
1047  /* Don't include LBRR frames if we don't have one. */
1048  if (regularity == dropus_silk_frame_regularity_lbrr && (pFlagsLBRR[iChannel] & (1 << iSILKFrame)) == 0) {
1049  continue;
1050  }
1051 
1052  /* The mid channel is always the first one in a SILK frame. */
1053  if (iChannel == 0) {
1054  n = dropus_range_decoder_decode(pRD, f_Stage1, DROPUS_COUNTOF(f_Stage1), ft_Stage1);
1055  i0 = dropus_range_decoder_decode(pRD, f_Stage2, DROPUS_COUNTOF(f_Stage2), ft_Stage2);
1056  i1 = dropus_range_decoder_decode(pRD, f_Stage3, DROPUS_COUNTOF(f_Stage3), ft_Stage3);
1057  i2 = dropus_range_decoder_decode(pRD, f_Stage2, DROPUS_COUNTOF(f_Stage2), ft_Stage2);
1058  i3 = dropus_range_decoder_decode(pRD, f_Stage3, DROPUS_COUNTOF(f_Stage3), ft_Stage3);
1059 
1060  wi0 = i0 + 3 * (n / 5);
1061  wi1 = i2 + 3 * (n % 5);
1062 
1063  #if 0
1064  /* Note that w0_Q13 depends on w1_Q13 so must be calculated afterwards. */
1065  w1_Q13 = dropus_Q13(wi1) + (((dropus_Q13((dropus_uint16)(wi1 + 1)) - dropus_Q13(wi1)) * 6554) >> 16) * ((2 * i3) + 1);
1066  w0_Q13 = dropus_Q13(wi0) + (((dropus_Q13((dropus_uint16)(wi0 + 1)) - dropus_Q13(wi0)) * 6554) >> 16) * ((2 * i1) + 1) - w1_Q13;
1067 
1068  /* RFC 6716 - Section 4.2.7.2 - Mid-Only Flag */
1069  {
1070  dropus_uint16 f_MOF[] = {192, 64}, ft_MOF = 256;
1071  midOnlyFlag = (dropus_uint8)dropus_range_decoder_decode(pRD, f_MOF, DROPUS_COUNTOF(f_MOF), ft_MOF);
1072  }
1073  #endif
1074  }
1075  }
1076 }
1077 
1078 static dropus_result dropus_stream_decode_silk_frames__stereo(dropus_stream* pOpusStream, dropus_range_decoder* pRD, dropus_silk_frame_regularity regularity, dropus_uint8* pFlagsVAD, dropus_uint8* pFlagsLBRR, dropus_silk_frame* pSILKFrames)
1079 {
1080  dropus_result result;
1081  dropus_uint8 silkFrameCount;
1082  dropus_uint8 iSILKFrame;
1083 
1084  silkFrameCount = dropus_toc_silk_frame_count(pOpusStream->packet.toc);
1085  DROPUS_ASSERT(silkFrameCount > 0);
1086 
1087  for (iSILKFrame = 0; iSILKFrame < silkFrameCount; iSILKFrame += 1) {
1088  result = dropus_stream_decode_silk_frame__stereo(pOpusStream, pRD, regularity, iSILKFrame, pFlagsVAD, pFlagsLBRR, pSILKFrames);
1089  if (result != DROPUS_SUCCESS) {
1090  return result;
1091  }
1092  }
1093 
1094  return DROPUS_SUCCESS;
1095 }
1096 
1097 
1098 static dropus_result dropus_stream_decode_frame__silk(dropus_stream* pOpusStream, dropus_stream_frame* pOpusFrame, const dropus_uint8* pData, size_t dataSize)
1099 {
1100  dropus_result result;
1101  dropus_range_decoder rd;
1102 
1103  DROPUS_ASSERT(pOpusStream != NULL);
1104  DROPUS_ASSERT(pOpusFrame != NULL);
1105  DROPUS_ASSERT(pData != NULL);
1106  DROPUS_ASSERT(dataSize <= DROPUS_MAX_FRAME_SIZE_IN_BYTES);
1107 
1108  pOpusFrame->sizeInBytes = (dropus_uint16)dataSize; /* Safe cast because dataSize <= DROPUS_MAX_FRAME_SIZE_IN_BYTES <= 1275. */
1109 
1110  /* Everything is fed through the range decoder. */
1111  dropus_range_decoder_init(pData, pOpusFrame->sizeInBytes, &rd);
1112  {
1113  dropus_uint16 f_Flags[2] = {1, 1}, ft_Flags = 2;
1114 
1115  dropus_uint8 iChannel;
1116  dropus_uint8 channels;
1117  dropus_uint8 iFrameSILK;
1118  dropus_uint8 frameCountSILK;
1119  dropus_uint16 k;
1120  dropus_uint8 flagsVAD[2] = {0, 0}; /* One for each channel. */
1121  dropus_uint8 flagsLBRR[2] = {0, 0}; /* One for each channel. */
1122  dropus_silk_frame silkFrames_LBRR[2][3];
1123  dropus_silk_frame silkFrames_Regular[2][3];
1124 
1125  dropus_uint32 w0_Q13[3] = {0, 0, 0}; /* One for each SILK frame (max 3). */
1126  dropus_uint32 w1_Q13[3] = {0, 0, 0}; /* One for each SILK frame (max 3). */
1127  dropus_uint8 midOnlyFlag[3] = {0, 0, 0}; /* One for each SILK frame (max 3). */
1128 
1129  frameCountSILK = dropus_toc_silk_frame_count(pOpusStream->packet.toc); /* SILK frame count. Between 1 and 3. Either 1 10ms SILK frame, or between 1 and 3 20ms frames (20ms, 40ms, 60ms). */
1130  if (frameCountSILK == 0) {
1131  return DROPUS_BAD_DATA;
1132  }
1133 
1134  channels = dropus_toc_s(pOpusStream->packet.toc) + 1;
1135 
1136  /* Header flags. */
1137  for (iChannel = 0; iChannel < channels; ++iChannel) {
1138  for (iFrameSILK = 0; iFrameSILK < frameCountSILK; ++iFrameSILK) {
1139  k = dropus_range_decoder_decode(&rd, f_Flags, DROPUS_COUNTOF(f_Flags), ft_Flags);
1140  DROPUS_ASSERT(k <= 1);
1141  flagsVAD[iChannel] |= (k << iFrameSILK);
1142  }
1143 
1144  k = dropus_range_decoder_decode(&rd, f_Flags, DROPUS_COUNTOF(f_Flags), ft_Flags);
1145  DROPUS_ASSERT(k <= 1);
1146  flagsLBRR[iChannel] = (dropus_uint8)k;
1147  }
1148 
1149  /* RFC 6716 - 4.2.4. Per-Frame LBRR Flags. */
1150  if (frameCountSILK > 1) {
1151  dropus_uint8 iChannel;
1152  for (iChannel = 0; iChannel < channels; iChannel += 1) {
1153  dropus_uint16 f_40[4] = {0, 53, 53, 150}, ft_40 = 256;
1154  dropus_uint16 f_60[8] = {0, 41, 20, 29, 41, 15, 28, 82}, ft_60 = 256;
1155  if (flagsLBRR[iChannel] != 0) {
1156  if (frameCountSILK == 2) {
1157  k = dropus_range_decoder_decode(&rd, f_40, DROPUS_COUNTOF(f_40), ft_40);
1158  DROPUS_ASSERT(k <= 0b11);
1159  } else {
1160  DROPUS_ASSERT(frameCountSILK == 3);
1161  k = dropus_range_decoder_decode(&rd, f_60, DROPUS_COUNTOF(f_60), ft_60);
1162  DROPUS_ASSERT(k <= 0b111);
1163  }
1164 
1165  flagsLBRR[iChannel] = (dropus_uint8)k;
1166  }
1167  }
1168  }
1169 
1170  /* LBRR frames. Only do this if the relevant flag is set. */
1171  for (iFrameSILK = 0; iFrameSILK < frameCountSILK; ++iFrameSILK) {
1172  if (channels == 1) {
1173  /*result = dropus_stream_decode_silk_frames__mono(pOpusStream, &rd, );*/
1174  } else {
1175  result = dropus_stream_decode_silk_frames__stereo(pOpusStream, &rd, dropus_silk_frame_regularity_lbrr, flagsVAD, flagsLBRR, silkFrames_LBRR);
1176  }
1177 
1178  for (iChannel = 0; iChannel < channels; ++iChannel) {
1179  if ((flagsLBRR[iChannel] & (1 << iFrameSILK)) != 0) {
1180  result = dropus_stream_decode_frame__silk_frame(pOpusStream, &rd, &silkFrames_LBRR[iFrameSILK]);
1181  if (result != DROPUS_SUCCESS) {
1182  return result;
1183  }
1184  }
1185  }
1186  }
1187 
1188  /* TODO: Don't forget to set the previous stereo weights. Don't just blindly set it without first checking the rules in RFC 6716 - Section 4.2.7.1. */
1189  /* RFC 6716 - Section 4.2.7.1 - These prediction weights are never included in a mono Opus frame, and the previous weights are reset to zeros on any transition from mono to stereo. */
1190  if (channels == 1) {
1191  pOpusStream->silk.w0_Q13_prev = 0;
1192  pOpusStream->silk.w1_Q13_prev = 0;
1193  }
1194 
1195 
1196  }
1197 
1198  return DROPUS_SUCCESS;
1199 }
1200 
1201 static dropus_result dropus_stream_decode_frame__celt(dropus_stream* pOpusStream, dropus_stream_frame* pOpusFrame, const dropus_uint8* pData, size_t dataSize)
1202 {
1203  dropus_range_decoder rd;
1204 
1205  DROPUS_ASSERT(pOpusStream != NULL);
1206  DROPUS_ASSERT(pOpusFrame != NULL);
1207  DROPUS_ASSERT(pData != NULL);
1208  DROPUS_ASSERT(dataSize <= DROPUS_MAX_FRAME_SIZE_IN_BYTES);
1209 
1210  pOpusFrame->sizeInBytes = (dropus_uint16)dataSize; /* Safe cast because dataSize <= DROPUS_MAX_FRAME_SIZE_IN_BYTES <= 1275. */
1211 
1212  /* Everything is fed through the range decoder. */
1213  dropus_range_decoder_init(pData, pOpusFrame->sizeInBytes, &rd);
1214  {
1215 
1216  }
1217 
1218  return DROPUS_SUCCESS;
1219 }
1220 
1221 static dropus_result dropus_stream_decode_frame__hybrid(dropus_stream* pOpusStream, dropus_stream_frame* pOpusFrame, const dropus_uint8* pData, size_t dataSize)
1222 {
1223  dropus_range_decoder rd;
1224 
1225  DROPUS_ASSERT(pOpusStream != NULL);
1226  DROPUS_ASSERT(pOpusFrame != NULL);
1227  DROPUS_ASSERT(pData != NULL);
1228  DROPUS_ASSERT(dataSize <= DROPUS_MAX_FRAME_SIZE_IN_BYTES);
1229 
1230  pOpusFrame->sizeInBytes = (dropus_uint16)dataSize; /* Safe cast because dataSize <= DROPUS_MAX_FRAME_SIZE_IN_BYTES <= 1275. */
1231 
1232  /* Everything is fed through the range decoder. */
1233  dropus_range_decoder_init(pData, pOpusFrame->sizeInBytes, &rd);
1234  {
1235 
1236  }
1237 
1238  return DROPUS_SUCCESS;
1239 }
1240 
1241 DROPUS_API dropus_result dropus_stream_decode_packet(dropus_stream* pOpusStream, const void* pData, size_t dataSize)
1242 {
1243  const dropus_uint8* pRunningData8 = (const dropus_uint8*)pData;
1244  dropus_uint8 toc; /* Table of Contents byte. */
1245  dropus_uint8 opusFrameCount;
1247  dropus_uint32 code; /* Determines the structure of the Opus packet. */
1248 
1249  if (pOpusStream == NULL || pData == NULL) {
1250  return DROPUS_INVALID_ARGS;
1251  }
1252 
1253  DROPUS_ASSERT(DROPUS_MAX_PACKET_SIZE_IN_BYTES < 65536);
1254  if (dataSize > DROPUS_MAX_PACKET_SIZE_IN_BYTES) {
1255  return DROPUS_BAD_DATA;
1256  }
1257 
1258  /* RFC 6716 - Section 3.4 [R1] Packets are at least one byte. */
1259  if (dataSize < 1) {
1260  return DROPUS_BAD_DATA;
1261  }
1262 
1263  /* The TOC byte specifies the structure of the packet. */
1264  toc = pRunningData8[0];
1265  pRunningData8 += 1;
1266 
1267  /*
1268  We need to look at the code to know the frames making up the packet are structured. We will do a pre-processing step to
1269  extract basic information about each frame in the packet.
1270  */
1271  code = dropus_toc_c(toc);
1272  switch (code) {
1273  case 0: /* RFC 6716 - Section 3.2.2. Code 0: One Frame in the Packet */
1274  {
1275  dropus_uint16 opusFrameSize = (dropus_uint16)(dataSize-1);
1276 
1277  /* RFC 6716 - Section 3.4 [R2] No implicit frame length is larger than 1275 bytes. */
1278  if (opusFrameSize > DROPUS_MAX_FRAME_SIZE_IN_BYTES) {
1279  return DROPUS_BAD_DATA;
1280  }
1281 
1282  opusFrameCount = 1;
1283  opusFrameSizes[0] = opusFrameSize;
1284  } break;
1285 
1286  case 1: /* RFC 6716 - Section 3.2.3. Code 1: Two Frames in the Packet, Each with Equal Compressed Size */
1287  {
1288  dropus_uint16 opusFrameSize;
1289 
1290  /* RFC 6716 - Section 3.4 [R3] Code 1 packets have an odd total length, N, so that (N-1)/2 is an integer. */
1291  if ((dataSize & 1) == 0) {
1292  return DROPUS_BAD_DATA;
1293  }
1294 
1295  opusFrameSize = (dropus_uint16)(dataSize-1)/2;
1296 
1297  /* RFC 6716 - Section 3.4 [R2] No implicit frame length is larger than 1275 bytes. */
1298  if (opusFrameSize > DROPUS_MAX_FRAME_SIZE_IN_BYTES) {
1299  return DROPUS_BAD_DATA;
1300  }
1301 
1302  opusFrameCount = 2;
1303  opusFrameSizes[0] = opusFrameSize;
1304  opusFrameSizes[1] = opusFrameSize;
1305  } break;
1306 
1307  case 2: /* RFC 6716 - Section 3.2.4. Code 2: Two Frames in the Packet, with Different Compressed Sizes */
1308  {
1309  dropus_uint8 byte0;
1310  dropus_uint8 byte1;
1311  dropus_uint16 opusFrameSize0 = 0;
1312  dropus_uint16 opusFrameSize1 = 0;
1313  dropus_uint16 headerByteCount;
1314 
1315  /* RFC 6716 - Section 3.4 [R4] Code 2 packets have enough bytes after the TOC for a valid frame length, and that length is no larger than the number of bytes remaining in the packet. */
1316  if (dataSize < 2) {
1317  return DROPUS_BAD_DATA;
1318  }
1319 
1320  /* RFC 6716 - Section 3.2.1. Frame Length Coding */
1321  byte0 = pRunningData8[0]; pRunningData8 += 1;
1322  if (byte0 == 0) {
1323  /*
1324  Section 3.2.1 of RFC 6716 says the following:
1325 
1326  "Any Opus frame in any mode MAY have a length of 0.
1327 
1328  This implies to me that this is a valid case. dr_opus is going to handle this by setting the PCM frame count to 0 for this packet.
1329  */
1330  opusFrameSize0 = 0;
1331  opusFrameSize1 = 0;
1332  } else {
1333  if (byte0 >= 1 && byte0 <= 251) {
1334  opusFrameSize0 = byte0;
1335  }
1336  if (byte0 >= 252 /*&& byte0 <= 255*/) {
1337  /* RFC 6716 - Section 3.4 [R4] Code 2 packets have enough bytes after the TOC for a valid frame length, and that length is no larger than the number of bytes remaining in the packet. */
1338  if (dataSize < 3) {
1339  return DROPUS_BAD_DATA;
1340  }
1341 
1342  byte1 = pRunningData8[0]; pRunningData8 += 1;
1343  opusFrameSize0 = (byte1*4) + byte0;
1344  }
1345 
1346  headerByteCount = (dropus_uint16)(pRunningData8 - (const dropus_uint8*)pData); /* This is a safe case because the maximum difference will be 3. */
1347 
1348  /* RFC 6716 - Section 3.4 [R2] No implicit frame length is larger than 1275 bytes. */
1349  if (opusFrameSize0 > DROPUS_MAX_FRAME_SIZE_IN_BYTES) {
1350  return DROPUS_BAD_DATA;
1351  }
1352 
1353  /* RFC 6716 - Section 3.4 [R4] Code 2 packets have enough bytes after the TOC for a valid frame length, and that length is no larger than the number of bytes remaining in the packet. */
1354  if ((dataSize-headerByteCount) > dataSize) {
1355  return DROPUS_BAD_DATA;
1356  }
1357 
1358  opusFrameSize1 = (dropus_uint16)(dataSize-headerByteCount-opusFrameSize0); /* Safe cast because dataSize is guaranteed to be < 65536 at this point since it was checked at the top of this function. */
1359 
1360  /* RFC 6716 - Section 3.4 [R2] No implicit frame length is larger than 1275 bytes. */
1361  if (opusFrameSize1 > DROPUS_MAX_FRAME_SIZE_IN_BYTES) {
1362  return DROPUS_BAD_DATA;
1363  }
1364 
1365  /* RFC 6716 - Section 3.4 [R4] Code 2 packets have enough bytes after the TOC for a valid frame length, and that length is no larger than the number of bytes remaining in the packet. */
1366  if ((size_t)(headerByteCount + opusFrameSize0 + opusFrameSize1) > dataSize) {
1367  return DROPUS_BAD_DATA;
1368  }
1369  }
1370 
1371  opusFrameCount = 2;
1372  opusFrameSizes[0] = opusFrameSize0;
1373  opusFrameSizes[1] = opusFrameSize1;
1374  } break;
1375 
1376  case 3: /* RFC 6716 - Section 3.2.5. Code 3: A Signaled Number of Frames in the Packet */
1377  {
1378  dropus_uint16 iFrame;
1379  dropus_uint8 frameCountByte;
1380  dropus_uint8 v; /* Is VBR? */
1381  dropus_uint8 p; /* Has padding? */
1382  dropus_uint8 M; /* Frame count. */
1383  dropus_uint16 P; /* The size of the padding. Must never be more than dataSize-2. */
1384  dropus_uint16 R; /* The number of bytes remaining in the packet after subtracting the TOC, frame count byte and padding. */
1385  dropus_uint32 ms; /* Total length in milliseconds. */
1386  dropus_uint32 paddingByteCount; /* The number of bytes making up the size of the padding. Only used for validation. */
1387 
1388  /*
1389  RFC 6716 - Section 3.2.5:
1390  "Code 3 packets MUST have at least 2 bytes [R6,R7]."
1391  */
1392  if (dataSize < 2) {
1393  return DROPUS_BAD_DATA;
1394  }
1395 
1396  frameCountByte = pRunningData8[0]; pRunningData8 += 1;
1397  v = (frameCountByte & 0x80) >> 7;
1398  p = (frameCountByte & 0x40) >> 6;
1399  M = (frameCountByte & 0x3F);
1400 
1401  /* RFC 6716 - Section 3.4 [R5] Code 3 packets contain at least one frame, but no more than 120 ms of audio total. */
1402  ms = (M * dropus_toc_frame_size_in_pcm_frames(toc)) / dropus_toc_sample_rate_ms(toc);
1403  if (M < 1 || ms > 120) {
1404  return DROPUS_BAD_DATA;
1405  }
1406 
1407  /* Sanity check to ensure the frame count is never greather than the maximum allowed. */
1409  return DROPUS_BAD_DATA;
1410  }
1411 
1412  /* Padding bytes. Need to run this in a loop. */
1413  P = 0;
1414  paddingByteCount = 0;
1415  if (p != 0) {
1416  size_t iPaddingByte;
1417  for (iPaddingByte = 0; iPaddingByte < dataSize-2; ++iPaddingByte) {
1418  dropus_uint8 paddingByte = pRunningData8[0]; pRunningData8 += 1;
1419  P += paddingByte;
1420  paddingByteCount += 1;
1421 
1422  /* A padding byte not equal to 255 signals the last padding byte. */
1423  if (paddingByte == 255) {
1424  /* There must be an additional byte available in this case. */
1425  if (iPaddingByte+1 >= dataSize-2) {
1426  return DROPUS_BAD_DATA;
1427  }
1428  } else {
1429  break; /* Reached the end of the padding bytes. */
1430  }
1431  }
1432  }
1433 
1434  /* Safety check. */
1435  if (P > dataSize-2) {
1436  return DROPUS_BAD_DATA;
1437  }
1438 
1439  /* R = bytes remaining. */
1440  R = (dropus_uint16)(dataSize-2-P);
1441 
1442  if (v == 0) {
1443  /* CBR */
1444  dropus_uint16 frameSize = R/M;
1445 
1446  /* RFC 6716 - Section 3.4 [R2] No implicit frame length is larger than 1275 bytes. */
1447  if (frameSize > DROPUS_MAX_FRAME_SIZE_IN_BYTES) {
1448  return DROPUS_BAD_DATA;
1449  }
1450 
1451  /* RFC 6716 - Section 3.4 [R6] ... */
1452  if (dataSize < 2) { /* ... The length of a CBR code 3 packet, N, is at least two bytes ... */
1453  return DROPUS_BAD_DATA;
1454  }
1455  if (paddingByteCount+P > dataSize-2) { /* ... the number of bytes added to indicate the padding size plus the trailing padding bytes themselves, P, is no more than N-2 ... */
1456  return DROPUS_BAD_DATA;
1457  }
1458  if (frameSize*M != (dropus_uint16)(dataSize-2-P)) { /* ... the frame count, M, satisfies the constraint that (N-2-P) is a non-negative integer multiple of M ... */
1459  return DROPUS_BAD_DATA;
1460  }
1461 
1462  opusFrameCount = M;
1463  for (iFrame = 0; iFrame < opusFrameCount; ++iFrame) {
1464  opusFrameSizes[iFrame] = frameSize;
1465  }
1466  } else {
1467  /* VBR */
1468  dropus_uint16 totalFrameSizeExceptLast = 0; /* Used later for checking [R7]. */
1469  dropus_uintptr headerSizeInBytes; /* For validation and deriving the size of the last frame. */
1470 
1471  opusFrameCount = M;
1472  for (iFrame = 0; iFrame < opusFrameCount-1; ++iFrame) {
1473  dropus_uint8 byte0;
1474  dropus_uint8 byte1;
1475 
1476  if (pRunningData8 >= ((const dropus_uint8*)pData) + dataSize) {
1477  return DROPUS_BAD_DATA; /* Ran out of data in the packet. Implicitly handles part of [R7]. */
1478  }
1479 
1480  byte0 = pRunningData8[0]; pRunningData8 += 1;
1481  if (byte0 == 0) {
1482  opusFrameSizes[iFrame] = 0;
1483  } else {
1484  if (byte0 >= 1 && byte0 <= 251) {
1485  opusFrameSizes[iFrame] = byte0;
1486  }
1487  if (byte0 >= 252 /*&& byte0 <= 255*/) {
1488  if (pRunningData8 >= ((const dropus_uint8*)pData) + dataSize) {
1489  return DROPUS_BAD_DATA; /* Ran out of data in the packet. Implicitly handles part of [R7]. */
1490  }
1491 
1492  byte1 = pRunningData8[0]; pRunningData8 += 1;
1493  opusFrameSizes[iFrame] = (byte1*4) + byte0;
1494 
1495  /* RFC 6716 - Section 3.4 [R2] No implicit frame length is larger than 1275 bytes. */
1496  if (opusFrameSizes[iFrame] > DROPUS_MAX_FRAME_SIZE_IN_BYTES) {
1497  return DROPUS_BAD_DATA;
1498  }
1499  }
1500  }
1501 
1502  totalFrameSizeExceptLast += opusFrameSizes[iFrame];
1503  }
1504 
1505  headerSizeInBytes = (dropus_uintptr)(pRunningData8 - (const dropus_uint8*)pData);
1506 
1507  /*
1508  RFC 6716 - Section 3.4 [R6]
1509  VBR code 3 packets are large enough to contain all the header
1510  bytes (TOC byte, frame count byte, any padding length bytes,
1511  and any frame length bytes), plus the length of the first M-1
1512  frames, plus any trailing padding bytes.
1513  */
1514  if ((headerSizeInBytes + totalFrameSizeExceptLast + P) > dataSize) {
1515  return DROPUS_BAD_DATA;
1516  }
1517 
1518  /* The size of the last frame is derived. */
1519  opusFrameSizes[opusFrameCount-1] = (dropus_uint16)(dataSize - headerSizeInBytes - totalFrameSizeExceptLast - P); /* Safe cast thanks to the myriad of validation done beforehand. */
1520 
1521  /* RFC 6716 - Section 3.4 [R2] No implicit frame length is larger than 1275 bytes. */
1522  if (opusFrameSizes[opusFrameCount-1] > DROPUS_MAX_FRAME_SIZE_IN_BYTES) {
1523  return DROPUS_BAD_DATA;
1524  }
1525  }
1526  } break;
1527 
1528  /* Will never hit this, but need the default to keep some compilers quiet. */
1529  default: return DROPUS_BAD_DATA;
1530  }
1531 
1532  pOpusStream->packet.toc = toc;
1533 
1534  /* Make sure the frame count is within a valid range. */
1535  if (opusFrameCount > DROPUS_MAX_OPUS_FRAMES_PER_PACKET) {
1536  return DROPUS_BAD_DATA;
1537  }
1538 
1539  /* At this point, pRunningData8 should be sitting on the first byte of the first frame in the packet. */
1540 
1541  /* Decoding. */
1542  {
1543  dropus_result result;
1544  dropus_uint16 iFrame;
1545  dropus_mode mode;
1546 
1547  mode = dropus_toc_mode(pOpusStream->packet.toc);
1548 
1549  /* Would be slightly more optimal to pull the mode checks out of the loop, but it's more compact, readable and maintainable to do it inside. We can let the compiler decide what to do with it. */
1550  for (iFrame = 0; iFrame < opusFrameCount; ++iFrame) {
1551  /* */ if (mode == dropus_mode_silk) {
1552  result = dropus_stream_decode_frame__silk(pOpusStream, &pOpusStream->packet.frames[iFrame], pRunningData8, opusFrameSizes[iFrame]);
1553  } else if (mode == dropus_mode_celt) {
1554  result = dropus_stream_decode_frame__celt(pOpusStream, &pOpusStream->packet.frames[iFrame], pRunningData8, opusFrameSizes[iFrame]);
1555  } else {
1556  DROPUS_ASSERT(mode == dropus_mode_hybrid);
1557  result = dropus_stream_decode_frame__hybrid(pOpusStream, &pOpusStream->packet.frames[iFrame], pRunningData8, opusFrameSizes[iFrame]);
1558  }
1559 
1560  if (result != DROPUS_SUCCESS) {
1561  return result; /* Probably a corrupt frame. */
1562  }
1563 
1564  pRunningData8 += opusFrameSizes[iFrame];
1565  }
1566  }
1567 
1568  return DROPUS_SUCCESS;
1569 }
1570 
1571 
1572 
1573 /***********************************************************************************************************************************************************
1574 
1575 High-Level Opus Decoding API
1576 
1577 ************************************************************************************************************************************************************/
1578 static void* dropus__malloc_default(size_t sz, void* pUserData)
1579 {
1580  (void)pUserData;
1581  return DROPUS_MALLOC(sz);
1582 }
1583 
1584 static void* dropus__realloc_default(void* p, size_t sz, void* pUserData)
1585 {
1586  (void)pUserData;
1587  return DROPUS_REALLOC(p, sz);
1588 }
1589 
1590 static void dropus__free_default(void* p, void* pUserData)
1591 {
1592  (void)pUserData;
1593  DROPUS_FREE(p);
1594 }
1595 
1596 
1597 static void* dropus__malloc_from_callbacks(size_t sz, const dropus_allocation_callbacks* pAllocationCallbacks)
1598 {
1599  if (pAllocationCallbacks == NULL) {
1600  return NULL;
1601  }
1602 
1603  if (pAllocationCallbacks->onMalloc != NULL) {
1604  return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
1605  }
1606 
1607  /* Try using realloc(). */
1608  if (pAllocationCallbacks->onRealloc != NULL) {
1609  return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
1610  }
1611 
1612  return NULL;
1613 }
1614 
1615 static void* dropus__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const dropus_allocation_callbacks* pAllocationCallbacks)
1616 {
1617  if (pAllocationCallbacks == NULL) {
1618  return NULL;
1619  }
1620 
1621  if (pAllocationCallbacks->onRealloc != NULL) {
1622  return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
1623  }
1624 
1625  /* Try emulating realloc() in terms of malloc()/free(). */
1626  if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
1627  void* p2;
1628 
1629  p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
1630  if (p2 == NULL) {
1631  return NULL;
1632  }
1633 
1634  if (p != NULL) {
1635  DROPUS_COPY_MEMORY(p2, p, szOld);
1636  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1637  }
1638 
1639  return p2;
1640  }
1641 
1642  return NULL;
1643 }
1644 
1645 static void dropus__free_from_callbacks(void* p, const dropus_allocation_callbacks* pAllocationCallbacks)
1646 {
1647  if (p == NULL || pAllocationCallbacks == NULL) {
1648  return;
1649  }
1650 
1651  if (pAllocationCallbacks->onFree != NULL) {
1652  pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
1653  }
1654 }
1655 
1656 
1657 static dropus_allocation_callbacks dropus__copy_allocation_callbacks_or_defaults(const dropus_allocation_callbacks* pAllocationCallbacks)
1658 {
1659  if (pAllocationCallbacks != NULL) {
1660  /* Copy. */
1661  return *pAllocationCallbacks;
1662  } else {
1663  /* Defaults. */
1664  dropus_allocation_callbacks allocationCallbacks;
1665  allocationCallbacks.pUserData = NULL;
1666  allocationCallbacks.onMalloc = dropus__malloc_default;
1667  allocationCallbacks.onRealloc = dropus__realloc_default;
1668  allocationCallbacks.onFree = dropus__free_default;
1669  return allocationCallbacks;
1670  }
1671 }
1672 
1673 static dropus_result dropus_init_internal(dropus* pOpus, dropus_read_proc onRead, dropus_seek_proc onSeek, void* pUserData, const dropus_allocation_callbacks* pAllocationCallbacks)
1674 {
1675  DROPUS_ASSERT(pOpus != NULL);
1676  DROPUS_ASSERT(onRead != NULL);
1677 
1678  /* Must always have an onRead callback. */
1679  if (onRead == NULL) {
1680  return DROPUS_INVALID_ARGS;
1681  }
1682 
1683  pOpus->onRead = onRead;
1684  pOpus->onSeek = onSeek;
1685  pOpus->pUserData = pUserData;
1686  pOpus->allocationCallbacks = dropus__copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
1687 
1688  /* Basic validation for allocation callbacks. free() and at least one of malloc() or realloc() must be set. */
1690  return DROPUS_INVALID_ARGS;
1691  }
1692 
1693  /* TODO: Implement me. */
1694 
1695  return DROPUS_SUCCESS;
1696 }
1697 
1698 DROPUS_API dropus_result dropus_init(dropus* pOpus, dropus_read_proc onRead, dropus_seek_proc onSeek, void* pUserData, const dropus_allocation_callbacks* pAllocationCallbacks)
1699 {
1700  if (pOpus == NULL) {
1701  return DROPUS_INVALID_ARGS;
1702  }
1703 
1704  DROPUS_ZERO_OBJECT(pOpus);
1705 
1706  return dropus_init_internal(pOpus, onRead, onSeek, pUserData, pAllocationCallbacks);
1707 }
1708 
1709 #ifndef DR_OPUS_NO_STDIO
1710 #include <errno.h>
1711 static dropus_result dropus_result_from_errno(int e)
1712 {
1713  switch (e)
1714  {
1715  case 0: return DROPUS_SUCCESS;
1716  #ifdef EPERM
1717  case EPERM: return DROPUS_INVALID_OPERATION;
1718  #endif
1719  #ifdef ENOENT
1720  case ENOENT: return DROPUS_DOES_NOT_EXIST;
1721  #endif
1722  #ifdef ESRCH
1723  case ESRCH: return DROPUS_DOES_NOT_EXIST;
1724  #endif
1725  #ifdef EINTR
1726  case EINTR: return DROPUS_INTERRUPT;
1727  #endif
1728  #ifdef EIO
1729  case EIO: return DROPUS_IO_ERROR;
1730  #endif
1731  #ifdef ENXIO
1732  case ENXIO: return DROPUS_DOES_NOT_EXIST;
1733  #endif
1734  #ifdef E2BIG
1735  case E2BIG: return DROPUS_INVALID_ARGS;
1736  #endif
1737  #ifdef ENOEXEC
1738  case ENOEXEC: return DROPUS_INVALID_FILE;
1739  #endif
1740  #ifdef EBADF
1741  case EBADF: return DROPUS_INVALID_FILE;
1742  #endif
1743  #ifdef ECHILD
1744  case ECHILD: return DROPUS_ERROR;
1745  #endif
1746  #ifdef EAGAIN
1747  case EAGAIN: return DROPUS_UNAVAILABLE;
1748  #endif
1749  #ifdef ENOMEM
1750  case ENOMEM: return DROPUS_OUT_OF_MEMORY;
1751  #endif
1752  #ifdef EACCES
1753  case EACCES: return DROPUS_ACCESS_DENIED;
1754  #endif
1755  #ifdef EFAULT
1756  case EFAULT: return DROPUS_BAD_ADDRESS;
1757  #endif
1758  #ifdef ENOTBLK
1759  case ENOTBLK: return DROPUS_ERROR;
1760  #endif
1761  #ifdef EBUSY
1762  case EBUSY: return DROPUS_BUSY;
1763  #endif
1764  #ifdef EEXIST
1765  case EEXIST: return DROPUS_ALREADY_EXISTS;
1766  #endif
1767  #ifdef EXDEV
1768  case EXDEV: return DROPUS_ERROR;
1769  #endif
1770  #ifdef ENODEV
1771  case ENODEV: return DROPUS_DOES_NOT_EXIST;
1772  #endif
1773  #ifdef ENOTDIR
1774  case ENOTDIR: return DROPUS_NOT_DIRECTORY;
1775  #endif
1776  #ifdef EISDIR
1777  case EISDIR: return DROPUS_IS_DIRECTORY;
1778  #endif
1779  #ifdef EINVAL
1780  case EINVAL: return DROPUS_INVALID_ARGS;
1781  #endif
1782  #ifdef ENFILE
1783  case ENFILE: return DROPUS_TOO_MANY_OPEN_FILES;
1784  #endif
1785  #ifdef EMFILE
1786  case EMFILE: return DROPUS_TOO_MANY_OPEN_FILES;
1787  #endif
1788  #ifdef ENOTTY
1789  case ENOTTY: return DROPUS_INVALID_OPERATION;
1790  #endif
1791  #ifdef ETXTBSY
1792  case ETXTBSY: return DROPUS_BUSY;
1793  #endif
1794  #ifdef EFBIG
1795  case EFBIG: return DROPUS_TOO_BIG;
1796  #endif
1797  #ifdef ENOSPC
1798  case ENOSPC: return DROPUS_NO_SPACE;
1799  #endif
1800  #ifdef ESPIPE
1801  case ESPIPE: return DROPUS_BAD_SEEK;
1802  #endif
1803  #ifdef EROFS
1804  case EROFS: return DROPUS_ACCESS_DENIED;
1805  #endif
1806  #ifdef EMLINK
1807  case EMLINK: return DROPUS_TOO_MANY_LINKS;
1808  #endif
1809  #ifdef EPIPE
1810  case EPIPE: return DROPUS_BAD_PIPE;
1811  #endif
1812  #ifdef EDOM
1813  case EDOM: return DROPUS_OUT_OF_RANGE;
1814  #endif
1815  #ifdef ERANGE
1816  case ERANGE: return DROPUS_OUT_OF_RANGE;
1817  #endif
1818  #ifdef EDEADLK
1819  case EDEADLK: return DROPUS_DEADLOCK;
1820  #endif
1821  #ifdef ENAMETOOLONG
1822  case ENAMETOOLONG: return DROPUS_PATH_TOO_LONG;
1823  #endif
1824  #ifdef ENOLCK
1825  case ENOLCK: return DROPUS_ERROR;
1826  #endif
1827  #ifdef ENOSYS
1828  case ENOSYS: return DROPUS_NOT_IMPLEMENTED;
1829  #endif
1830  #ifdef ENOTEMPTY
1831  case ENOTEMPTY: return DROPUS_DIRECTORY_NOT_EMPTY;
1832  #endif
1833  #ifdef ELOOP
1834  case ELOOP: return DROPUS_TOO_MANY_LINKS;
1835  #endif
1836  #ifdef ENOMSG
1837  case ENOMSG: return DROPUS_NO_MESSAGE;
1838  #endif
1839  #ifdef EIDRM
1840  case EIDRM: return DROPUS_ERROR;
1841  #endif
1842  #ifdef ECHRNG
1843  case ECHRNG: return DROPUS_ERROR;
1844  #endif
1845  #ifdef EL2NSYNC
1846  case EL2NSYNC: return DROPUS_ERROR;
1847  #endif
1848  #ifdef EL3HLT
1849  case EL3HLT: return DROPUS_ERROR;
1850  #endif
1851  #ifdef EL3RST
1852  case EL3RST: return DROPUS_ERROR;
1853  #endif
1854  #ifdef ELNRNG
1855  case ELNRNG: return DROPUS_OUT_OF_RANGE;
1856  #endif
1857  #ifdef EUNATCH
1858  case EUNATCH: return DROPUS_ERROR;
1859  #endif
1860  #ifdef ENOCSI
1861  case ENOCSI: return DROPUS_ERROR;
1862  #endif
1863  #ifdef EL2HLT
1864  case EL2HLT: return DROPUS_ERROR;
1865  #endif
1866  #ifdef EBADE
1867  case EBADE: return DROPUS_ERROR;
1868  #endif
1869  #ifdef EBADR
1870  case EBADR: return DROPUS_ERROR;
1871  #endif
1872  #ifdef EXFULL
1873  case EXFULL: return DROPUS_ERROR;
1874  #endif
1875  #ifdef ENOANO
1876  case ENOANO: return DROPUS_ERROR;
1877  #endif
1878  #ifdef EBADRQC
1879  case EBADRQC: return DROPUS_ERROR;
1880  #endif
1881  #ifdef EBADSLT
1882  case EBADSLT: return DROPUS_ERROR;
1883  #endif
1884  #ifdef EBFONT
1885  case EBFONT: return DROPUS_INVALID_FILE;
1886  #endif
1887  #ifdef ENOSTR
1888  case ENOSTR: return DROPUS_ERROR;
1889  #endif
1890  #ifdef ENODATA
1891  case ENODATA: return DROPUS_NO_DATA_AVAILABLE;
1892  #endif
1893  #ifdef ETIME
1894  case ETIME: return DROPUS_TIMEOUT;
1895  #endif
1896  #ifdef ENOSR
1897  case ENOSR: return DROPUS_NO_DATA_AVAILABLE;
1898  #endif
1899  #ifdef ENONET
1900  case ENONET: return DROPUS_NO_NETWORK;
1901  #endif
1902  #ifdef ENOPKG
1903  case ENOPKG: return DROPUS_ERROR;
1904  #endif
1905  #ifdef EREMOTE
1906  case EREMOTE: return DROPUS_ERROR;
1907  #endif
1908  #ifdef ENOLINK
1909  case ENOLINK: return DROPUS_ERROR;
1910  #endif
1911  #ifdef EADV
1912  case EADV: return DROPUS_ERROR;
1913  #endif
1914  #ifdef ESRMNT
1915  case ESRMNT: return DROPUS_ERROR;
1916  #endif
1917  #ifdef ECOMM
1918  case ECOMM: return DROPUS_ERROR;
1919  #endif
1920  #ifdef EPROTO
1921  case EPROTO: return DROPUS_ERROR;
1922  #endif
1923  #ifdef EMULTIHOP
1924  case EMULTIHOP: return DROPUS_ERROR;
1925  #endif
1926  #ifdef EDOTDOT
1927  case EDOTDOT: return DROPUS_ERROR;
1928  #endif
1929  #ifdef EBADMSG
1930  case EBADMSG: return DROPUS_BAD_MESSAGE;
1931  #endif
1932  #ifdef EOVERFLOW
1933  case EOVERFLOW: return DROPUS_TOO_BIG;
1934  #endif
1935  #ifdef ENOTUNIQ
1936  case ENOTUNIQ: return DROPUS_NOT_UNIQUE;
1937  #endif
1938  #ifdef EBADFD
1939  case EBADFD: return DROPUS_ERROR;
1940  #endif
1941  #ifdef EREMCHG
1942  case EREMCHG: return DROPUS_ERROR;
1943  #endif
1944  #ifdef ELIBACC
1945  case ELIBACC: return DROPUS_ACCESS_DENIED;
1946  #endif
1947  #ifdef ELIBBAD
1948  case ELIBBAD: return DROPUS_INVALID_FILE;
1949  #endif
1950  #ifdef ELIBSCN
1951  case ELIBSCN: return DROPUS_INVALID_FILE;
1952  #endif
1953  #ifdef ELIBMAX
1954  case ELIBMAX: return DROPUS_ERROR;
1955  #endif
1956  #ifdef ELIBEXEC
1957  case ELIBEXEC: return DROPUS_ERROR;
1958  #endif
1959  #ifdef EILSEQ
1960  case EILSEQ: return DROPUS_INVALID_DATA;
1961  #endif
1962  #ifdef ERESTART
1963  case ERESTART: return DROPUS_ERROR;
1964  #endif
1965  #ifdef ESTRPIPE
1966  case ESTRPIPE: return DROPUS_ERROR;
1967  #endif
1968  #ifdef EUSERS
1969  case EUSERS: return DROPUS_ERROR;
1970  #endif
1971  #ifdef ENOTSOCK
1972  case ENOTSOCK: return DROPUS_NOT_SOCKET;
1973  #endif
1974  #ifdef EDESTADDRREQ
1975  case EDESTADDRREQ: return DROPUS_NO_ADDRESS;
1976  #endif
1977  #ifdef EMSGSIZE
1978  case EMSGSIZE: return DROPUS_TOO_BIG;
1979  #endif
1980  #ifdef EPROTOTYPE
1981  case EPROTOTYPE: return DROPUS_BAD_PROTOCOL;
1982  #endif
1983  #ifdef ENOPROTOOPT
1984  case ENOPROTOOPT: return DROPUS_PROTOCOL_UNAVAILABLE;
1985  #endif
1986  #ifdef EPROTONOSUPPORT
1987  case EPROTONOSUPPORT: return DROPUS_PROTOCOL_NOT_SUPPORTED;
1988  #endif
1989  #ifdef ESOCKTNOSUPPORT
1990  case ESOCKTNOSUPPORT: return DROPUS_SOCKET_NOT_SUPPORTED;
1991  #endif
1992  #ifdef EOPNOTSUPP
1993  case EOPNOTSUPP: return DROPUS_INVALID_OPERATION;
1994  #endif
1995  #ifdef EPFNOSUPPORT
1996  case EPFNOSUPPORT: return DROPUS_PROTOCOL_FAMILY_NOT_SUPPORTED;
1997  #endif
1998  #ifdef EAFNOSUPPORT
1999  case EAFNOSUPPORT: return DROPUS_ADDRESS_FAMILY_NOT_SUPPORTED;
2000  #endif
2001  #ifdef EADDRINUSE
2002  case EADDRINUSE: return DROPUS_ALREADY_IN_USE;
2003  #endif
2004  #ifdef EADDRNOTAVAIL
2005  case EADDRNOTAVAIL: return DROPUS_ERROR;
2006  #endif
2007  #ifdef ENETDOWN
2008  case ENETDOWN: return DROPUS_NO_NETWORK;
2009  #endif
2010  #ifdef ENETUNREACH
2011  case ENETUNREACH: return DROPUS_NO_NETWORK;
2012  #endif
2013  #ifdef ENETRESET
2014  case ENETRESET: return DROPUS_NO_NETWORK;
2015  #endif
2016  #ifdef ECONNABORTED
2017  case ECONNABORTED: return DROPUS_NO_NETWORK;
2018  #endif
2019  #ifdef ECONNRESET
2020  case ECONNRESET: return DROPUS_CONNECTION_RESET;
2021  #endif
2022  #ifdef ENOBUFS
2023  case ENOBUFS: return DROPUS_NO_SPACE;
2024  #endif
2025  #ifdef EISCONN
2026  case EISCONN: return DROPUS_ALREADY_CONNECTED;
2027  #endif
2028  #ifdef ENOTCONN
2029  case ENOTCONN: return DROPUS_NOT_CONNECTED;
2030  #endif
2031  #ifdef ESHUTDOWN
2032  case ESHUTDOWN: return DROPUS_ERROR;
2033  #endif
2034  #ifdef ETOOMANYREFS
2035  case ETOOMANYREFS: return DROPUS_ERROR;
2036  #endif
2037  #ifdef ETIMEDOUT
2038  case ETIMEDOUT: return DROPUS_TIMEOUT;
2039  #endif
2040  #ifdef ECONNREFUSED
2041  case ECONNREFUSED: return DROPUS_CONNECTION_REFUSED;
2042  #endif
2043  #ifdef EHOSTDOWN
2044  case EHOSTDOWN: return DROPUS_NO_HOST;
2045  #endif
2046  #ifdef EHOSTUNREACH
2047  case EHOSTUNREACH: return DROPUS_NO_HOST;
2048  #endif
2049  #ifdef EALREADY
2050  case EALREADY: return DROPUS_IN_PROGRESS;
2051  #endif
2052  #ifdef EINPROGRESS
2053  case EINPROGRESS: return DROPUS_IN_PROGRESS;
2054  #endif
2055  #ifdef ESTALE
2056  case ESTALE: return DROPUS_INVALID_FILE;
2057  #endif
2058  #ifdef EUCLEAN
2059  case EUCLEAN: return DROPUS_ERROR;
2060  #endif
2061  #ifdef ENOTNAM
2062  case ENOTNAM: return DROPUS_ERROR;
2063  #endif
2064  #ifdef ENAVAIL
2065  case ENAVAIL: return DROPUS_ERROR;
2066  #endif
2067  #ifdef EISNAM
2068  case EISNAM: return DROPUS_ERROR;
2069  #endif
2070  #ifdef EREMOTEIO
2071  case EREMOTEIO: return DROPUS_IO_ERROR;
2072  #endif
2073  #ifdef EDQUOT
2074  case EDQUOT: return DROPUS_NO_SPACE;
2075  #endif
2076  #ifdef ENOMEDIUM
2077  case ENOMEDIUM: return DROPUS_DOES_NOT_EXIST;
2078  #endif
2079  #ifdef EMEDIUMTYPE
2080  case EMEDIUMTYPE: return DROPUS_ERROR;
2081  #endif
2082  #ifdef ECANCELED
2083  case ECANCELED: return DROPUS_CANCELLED;
2084  #endif
2085  #ifdef ENOKEY
2086  case ENOKEY: return DROPUS_ERROR;
2087  #endif
2088  #ifdef EKEYEXPIRED
2089  case EKEYEXPIRED: return DROPUS_ERROR;
2090  #endif
2091  #ifdef EKEYREVOKED
2092  case EKEYREVOKED: return DROPUS_ERROR;
2093  #endif
2094  #ifdef EKEYREJECTED
2095  case EKEYREJECTED: return DROPUS_ERROR;
2096  #endif
2097  #ifdef EOWNERDEAD
2098  case EOWNERDEAD: return DROPUS_ERROR;
2099  #endif
2100  #ifdef ENOTRECOVERABLE
2101  case ENOTRECOVERABLE: return DROPUS_ERROR;
2102  #endif
2103  #ifdef ERFKILL
2104  case ERFKILL: return DROPUS_ERROR;
2105  #endif
2106  #ifdef EHWPOISON
2107  case EHWPOISON: return DROPUS_ERROR;
2108  #endif
2109  default: return DROPUS_ERROR;
2110  }
2111 }
2112 
2113 static dropus_result dropus_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
2114 {
2115 #if defined(_MSC_VER) && _MSC_VER >= 1400
2116  errno_t err;
2117 #endif
2118 
2119  if (ppFile != NULL) {
2120  *ppFile = NULL; /* Safety. */
2121  }
2122 
2123  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
2124  return DROPUS_INVALID_ARGS;
2125  }
2126 
2127 #if defined(_MSC_VER) && _MSC_VER >= 1400
2128  err = fopen_s(ppFile, pFilePath, pOpenMode);
2129  if (err != 0) {
2130  return dropus_result_from_errno(err);
2131  }
2132 #else
2133 #if defined(_WIN32) || defined(__APPLE__)
2134  *ppFile = fopen(pFilePath, pOpenMode);
2135 #else
2136  #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
2137  *ppFile = fopen64(pFilePath, pOpenMode);
2138  #else
2139  *ppFile = fopen(pFilePath, pOpenMode);
2140  #endif
2141 #endif
2142  if (*ppFile == NULL) {
2143  dropus_result result = dropus_result_from_errno(errno);
2144  if (result == DROPUS_SUCCESS) {
2145  result = DROPUS_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
2146  }
2147 
2148  return result;
2149  }
2150 #endif
2151 
2152  return DROPUS_SUCCESS;
2153 }
2154 
2155 /*
2156 _wfopen() isn't always available in all compilation environments.
2157 
2158  * Windows only.
2159  * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
2160  * MinGW-64 (both 32- and 64-bit) seems to support it.
2161  * MinGW wraps it in !defined(__STRICT_ANSI__).
2162 
2163 This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
2164 fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
2165 */
2166 #if defined(_WIN32)
2167  #if defined(_MSC_VER) || defined(__MINGW64__) || !defined(__STRICT_ANSI__)
2168  #define DROPUS_HAS_WFOPEN
2169  #endif
2170 #endif
2171 
2172 static dropus_result dropus_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const dropus_allocation_callbacks* pAllocationCallbacks)
2173 {
2174  if (ppFile != NULL) {
2175  *ppFile = NULL; /* Safety. */
2176  }
2177 
2178  if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
2179  return DROPUS_INVALID_ARGS;
2180  }
2181 
2182 #if defined(DROPUS_HAS_WFOPEN)
2183  {
2184  /* Use _wfopen() on Windows. */
2185  #if defined(_MSC_VER) && _MSC_VER >= 1400
2186  errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
2187  if (err != 0) {
2188  return dropus_result_from_errno(err);
2189  }
2190  #else
2191  *ppFile = _wfopen(pFilePath, pOpenMode);
2192  if (*ppFile == NULL) {
2193  return dropus_result_from_errno(errno);
2194  }
2195  #endif
2196  (void)pAllocationCallbacks;
2197  }
2198 #else
2199  /*
2200  Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
2201  think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
2202  maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
2203  */
2204  {
2205  mbstate_t mbs;
2206  size_t lenMB;
2207  const wchar_t* pFilePathTemp = pFilePath;
2208  char* pFilePathMB = NULL;
2209  char pOpenModeMB[32] = {0};
2210 
2211  /* Get the length first. */
2212  DROPUS_ZERO_OBJECT(&mbs);
2213  lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
2214  if (lenMB == (size_t)-1) {
2215  return dropus_result_from_errno(errno);
2216  }
2217 
2218  pFilePathMB = (char*)dropus__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
2219  if (pFilePathMB == NULL) {
2220  return DROPUS_OUT_OF_MEMORY;
2221  }
2222 
2223  pFilePathTemp = pFilePath;
2224  DROPUS_ZERO_OBJECT(&mbs);
2225  wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
2226 
2227  /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
2228  {
2229  size_t i = 0;
2230  for (;;) {
2231  if (pOpenMode[i] == 0) {
2232  pOpenModeMB[i] = '\0';
2233  break;
2234  }
2235 
2236  pOpenModeMB[i] = (char)pOpenMode[i];
2237  i += 1;
2238  }
2239  }
2240 
2241  *ppFile = fopen(pFilePathMB, pOpenModeMB);
2242 
2243  dropus__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
2244  }
2245 
2246  if (*ppFile == NULL) {
2247  return DROPUS_ERROR;
2248  }
2249 #endif
2250 
2251  return DROPUS_SUCCESS;
2252 }
2253 
2254 
2255 static size_t dropus_on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
2256 {
2257  return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
2258 }
2259 
2260 static dropus_bool32 dropus_on_seek_stdio(void* pUserData, int offset, dropus_seek_origin origin)
2261 {
2262  return fseek((FILE*)pUserData, offset, (origin == dropus_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
2263 }
2264 
2265 DROPUS_API dropus_result dropus_init_file(dropus* pOpus, const char* pFilePath, const dropus_allocation_callbacks* pAllocationCallbacks)
2266 {
2267  dropus_result result;
2268  FILE* pFile;
2269 
2270  if (pOpus == NULL) {
2271  return DROPUS_INVALID_ARGS;
2272  }
2273 
2274  DROPUS_ZERO_OBJECT(pOpus);
2275 
2276  if (pFilePath == NULL || pFilePath[0] == '\0') {
2277  return DROPUS_INVALID_ARGS;
2278  }
2279 
2280  result = dropus_fopen(&pFile, pFilePath, "rb");
2281  if (result != DROPUS_SUCCESS) {
2282  return result;
2283  }
2284 
2285  pOpus->pFile = (void*)pFile;
2286 
2287  result = dropus_init_internal(pOpus, dropus_on_read_stdio, dropus_on_seek_stdio, NULL, pAllocationCallbacks);
2288  if (result != DROPUS_SUCCESS) {
2289  fclose(pFile);
2290  return result;
2291  }
2292 
2293  return DROPUS_SUCCESS;
2294 }
2295 
2296 DROPUS_API dropus_result dropus_init_file_w(dropus* pOpus, const wchar_t* pFilePath, const dropus_allocation_callbacks* pAllocationCallbacks)
2297 {
2298  dropus_result result;
2299  FILE* pFile;
2300 
2301  if (pOpus == NULL) {
2302  return DROPUS_INVALID_ARGS;
2303  }
2304 
2305  DROPUS_ZERO_OBJECT(pOpus);
2306 
2307  if (pFilePath == NULL || pFilePath[0] == '\0') {
2308  return DROPUS_INVALID_ARGS;
2309  }
2310 
2311  result = dropus_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks);
2312  if (result != DROPUS_SUCCESS) {
2313  return result;
2314  }
2315 
2316  pOpus->pFile = (void*)pFile;
2317 
2318  result = dropus_init_internal(pOpus, dropus_on_read_stdio, dropus_on_seek_stdio, NULL, pAllocationCallbacks);
2319  if (result != DROPUS_SUCCESS) {
2320  fclose(pFile);
2321  return result;
2322  }
2323 
2324  return DROPUS_SUCCESS;
2325 }
2326 #endif
2327 
2328 static size_t dropus_on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
2329 {
2330  size_t bytesRemaining;
2331  dropus* pOpus = (dropus*)pUserData;
2332 
2333  DROPUS_ASSERT(pOpus != NULL);
2334  DROPUS_ASSERT(pOpus->memory.dataSize >= pOpus->memory.currentReadPos);
2335 
2336  bytesRemaining = pOpus->memory.dataSize - pOpus->memory.currentReadPos;
2337  if (bytesToRead > bytesRemaining) {
2338  bytesToRead = bytesRemaining;
2339  }
2340 
2341  if (bytesToRead > 0) {
2342  DROPUS_COPY_MEMORY(pBufferOut, pOpus->memory.pData + pOpus->memory.currentReadPos, bytesToRead);
2343  pOpus->memory.currentReadPos += bytesToRead;
2344  }
2345 
2346  return bytesToRead;
2347 }
2348 
2349 static dropus_bool32 dropus_on_seek_memory(void* pUserData, int byteOffset, dropus_seek_origin origin)
2350 {
2351  dropus* pOpus = (dropus*)pUserData;
2352  DROPUS_ASSERT(pOpus != NULL);
2353 
2354  if (origin == dropus_seek_origin_current) {
2355  if (byteOffset > 0) {
2356  if (pOpus->memory.currentReadPos + byteOffset > pOpus->memory.dataSize) {
2357  byteOffset = (int)(pOpus->memory.dataSize - pOpus->memory.currentReadPos); /* Trying to seek too far forward. */
2358  }
2359  } else {
2360  if (pOpus->memory.currentReadPos < (size_t)-byteOffset) {
2361  byteOffset = -(int)pOpus->memory.currentReadPos; /* Trying to seek too far backwards. */
2362  }
2363  }
2364 
2365  /* This will never underflow thanks to the clamps above. */
2366  pOpus->memory.currentReadPos += byteOffset;
2367  } else {
2368  if ((dropus_uint32)byteOffset <= pOpus->memory.dataSize) {
2369  pOpus->memory.currentReadPos = byteOffset;
2370  } else {
2371  pOpus->memory.currentReadPos = pOpus->memory.dataSize; /* Trying to seek too far forward. */
2372  }
2373  }
2374 
2375  return DROPUS_TRUE;
2376 }
2377 
2378 DROPUS_API dropus_result dropus_init_memory(dropus* pOpus, const void* pData, size_t dataSize, const dropus_allocation_callbacks* pAllocationCallbacks)
2379 {
2380  if (pOpus == NULL) {
2381  return DROPUS_INVALID_ARGS;
2382  }
2383 
2384  DROPUS_ZERO_OBJECT(pOpus);
2385 
2386  if (pData == NULL || dataSize == 0) {
2387  return DROPUS_INVALID_ARGS;
2388  }
2389 
2390  pOpus->memory.pData = (const dropus_uint8*)pData;
2391  pOpus->memory.dataSize = dataSize;
2392  pOpus->memory.currentReadPos = 0;
2393 
2394  return dropus_init_internal(pOpus, dropus_on_read_memory, dropus_on_seek_memory, NULL, pAllocationCallbacks);
2395 }
2396 
2397 
2398 DROPUS_API void dropus_uninit(dropus* pOpus)
2399 {
2400  if (pOpus == NULL) {
2401  return;
2402  }
2403 
2404 #ifndef DR_OPUS_NO_STDIO
2405  /* Since dr_opus manages the stdio FILE object make sure it's closed on uninitialization. */
2406  if (pOpus->pFile != NULL) {
2407  fclose((FILE*)pOpus->pFile);
2408  }
2409 #endif
2410 }
2411 
2412 
2413 
2415 {
2416  switch (result)
2417  {
2418  case DROPUS_SUCCESS: return "No error";
2419  case DROPUS_ERROR: return "Unknown error";
2420  case DROPUS_INVALID_ARGS: return "Invalid argument";
2421  case DROPUS_INVALID_OPERATION: return "Invalid operation";
2422  case DROPUS_OUT_OF_MEMORY: return "Out of memory";
2423  case DROPUS_OUT_OF_RANGE: return "Out of range";
2424  case DROPUS_ACCESS_DENIED: return "Permission denied";
2425  case DROPUS_DOES_NOT_EXIST: return "Resource does not exist";
2426  case DROPUS_ALREADY_EXISTS: return "Resource already exists";
2427  case DROPUS_TOO_MANY_OPEN_FILES: return "Too many open files";
2428  case DROPUS_INVALID_FILE: return "Invalid file";
2429  case DROPUS_TOO_BIG: return "Too large";
2430  case DROPUS_PATH_TOO_LONG: return "Path too long";
2431  case DROPUS_NAME_TOO_LONG: return "Name too long";
2432  case DROPUS_NOT_DIRECTORY: return "Not a directory";
2433  case DROPUS_IS_DIRECTORY: return "Is a directory";
2434  case DROPUS_DIRECTORY_NOT_EMPTY: return "Directory not empty";
2435  case DROPUS_END_OF_FILE: return "End of file";
2436  case DROPUS_NO_SPACE: return "No space available";
2437  case DROPUS_BUSY: return "Device or resource busy";
2438  case DROPUS_IO_ERROR: return "Input/output error";
2439  case DROPUS_INTERRUPT: return "Interrupted";
2440  case DROPUS_UNAVAILABLE: return "Resource unavailable";
2441  case DROPUS_ALREADY_IN_USE: return "Resource already in use";
2442  case DROPUS_BAD_ADDRESS: return "Bad address";
2443  case DROPUS_BAD_SEEK: return "Illegal seek";
2444  case DROPUS_BAD_PIPE: return "Broken pipe";
2445  case DROPUS_DEADLOCK: return "Deadlock";
2446  case DROPUS_TOO_MANY_LINKS: return "Too many links";
2447  case DROPUS_NOT_IMPLEMENTED: return "Not implemented";
2448  case DROPUS_NO_MESSAGE: return "No message of desired type";
2449  case DROPUS_BAD_MESSAGE: return "Invalid message";
2450  case DROPUS_NO_DATA_AVAILABLE: return "No data available";
2451  case DROPUS_INVALID_DATA: return "Invalid data";
2452  case DROPUS_TIMEOUT: return "Timeout";
2453  case DROPUS_NO_NETWORK: return "Network unavailable";
2454  case DROPUS_NOT_UNIQUE: return "Not unique";
2455  case DROPUS_NOT_SOCKET: return "Socket operation on non-socket";
2456  case DROPUS_NO_ADDRESS: return "Destination address required";
2457  case DROPUS_BAD_PROTOCOL: return "Protocol wrong type for socket";
2458  case DROPUS_PROTOCOL_UNAVAILABLE: return "Protocol not available";
2459  case DROPUS_PROTOCOL_NOT_SUPPORTED: return "Protocol not supported";
2460  case DROPUS_PROTOCOL_FAMILY_NOT_SUPPORTED: return "Protocol family not supported";
2461  case DROPUS_ADDRESS_FAMILY_NOT_SUPPORTED: return "Address family not supported";
2462  case DROPUS_SOCKET_NOT_SUPPORTED: return "Socket type not supported";
2463  case DROPUS_CONNECTION_RESET: return "Connection reset";
2464  case DROPUS_ALREADY_CONNECTED: return "Already connected";
2465  case DROPUS_NOT_CONNECTED: return "Not connected";
2466  case DROPUS_CONNECTION_REFUSED: return "Connection refused";
2467  case DROPUS_NO_HOST: return "No host";
2468  case DROPUS_IN_PROGRESS: return "Operation in progress";
2469  case DROPUS_CANCELLED: return "Operation cancelled";
2470  case DROPUS_MEMORY_ALREADY_MAPPED: return "Memory already mapped";
2471  case DROPUS_AT_END: return "Reached end of collection";
2472 
2473  /* dr_opus specific result codes. */
2474  case DROPUS_CRC_MISMATCH: return "CRC mismatch";
2475  case DROPUS_BAD_DATA: return "Bad data";
2476 
2477  default: return "Unknown error";
2478  }
2479 }
2480 
2481 DROPUS_API void* dropus_malloc(size_t sz, const dropus_allocation_callbacks* pAllocationCallbacks)
2482 {
2483  if (pAllocationCallbacks == NULL) {
2484  return dropus__malloc_default(sz, NULL);
2485  } else {
2486  return dropus__malloc_from_callbacks(sz, pAllocationCallbacks);
2487  }
2488 }
2489 
2490 DROPUS_API void* dropus_realloc(void* p, size_t sz, const dropus_allocation_callbacks* pAllocationCallbacks)
2491 {
2492  if (pAllocationCallbacks == NULL) {
2493  return dropus__realloc_default(p, sz, NULL);
2494  } else {
2495  /*
2496  We need to do an explicit check for onRealloc because dropus__realloc_from_callbacks() will fall back to a malloc based emulation if onRealloc is missing
2497  which we do not want to do dropus_realloc().
2498  */
2499  if (pAllocationCallbacks->onRealloc == NULL) {
2500  return NULL;
2501  }
2502 
2503  return dropus__realloc_from_callbacks(p, sz, /*szOld*/ 0, pAllocationCallbacks); /* Safe to pass 0 for szOld thanks to the onRealloc check above. */
2504  }
2505 }
2506 
2507 DROPUS_API void dropus_free(void* p, const dropus_allocation_callbacks* pAllocationCallbacks)
2508 {
2509  if (pAllocationCallbacks == NULL) {
2510  dropus__free_default(p, NULL);
2511  } else {
2512  dropus__free_from_callbacks(p, pAllocationCallbacks);
2513  }
2514 }
2515 #endif /* DR_OPUS_IMPLEMENTATION */
2516 
2517 /*
2518 This software is available as a choice of the following licenses. Choose
2519 whichever you prefer.
2520 
2521 ===============================================================================
2522 ALTERNATIVE 1 - Public Domain (www.unlicense.org)
2523 ===============================================================================
2524 This is free and unencumbered software released into the public domain.
2525 
2526 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
2527 software, either in source code form or as a compiled binary, for any purpose,
2528 commercial or non-commercial, and by any means.
2529 
2530 In jurisdictions that recognize copyright laws, the author or authors of this
2531 software dedicate any and all copyright interest in the software to the public
2532 domain. We make this dedication for the benefit of the public at large and to
2533 the detriment of our heirs and successors. We intend this dedication to be an
2534 overt act of relinquishment in perpetuity of all present and future rights to
2535 this software under copyright law.
2536 
2537 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2538 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2539 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2540 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2541 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2542 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2543 
2544 For more information, please refer to <http://unlicense.org/>
2545 
2546 ===============================================================================
2547 ALTERNATIVE 2 - MIT No Attribution
2548 ===============================================================================
2549 Copyright 2020 David Reid
2550 
2551 Permission is hereby granted, free of charge, to any person obtaining a copy of
2552 this software and associated documentation files (the "Software"), to deal in
2553 the Software without restriction, including without limitation the rights to
2554 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
2555 of the Software, and to permit persons to whom the Software is furnished to do
2556 so.
2557 
2558 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2559 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2560 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2561 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2562 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2563 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2564 SOFTWARE.
2565 */
R
#define R
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:5104
dropus_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:253
dropus_uint16
uint16_t dropus_uint16
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:55
DROPUS_INVALID_OPERATION
#define DROPUS_INVALID_OPERATION
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:134
dropus::dataSize
size_t dataSize
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:271
dropus_uint32
uint32_t dropus_uint32
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:57
DROPUS_TOO_BIG
#define DROPUS_TOO_BIG
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:142
dropus_seek_origin
dropus_seek_origin
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:244
DROPUS_CANCELLED
#define DROPUS_CANCELLED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:182
DROPUS_BAD_PIPE
#define DROPUS_BAD_PIPE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:157
dropus_bool32
dropus_uint32 dropus_bool32
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:63
DROPUS_TOO_MANY_LINKS
#define DROPUS_TOO_MANY_LINKS
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:159
dropus_stream_decode_packet
DROPUS_API dropus_result dropus_stream_decode_packet(dropus_stream *pOpusStream, const void *pData, size_t dataSize)
dropus_seek_origin_current
@ dropus_seek_origin_current
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:251
dropus_mode
dropus_mode
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:199
DROPUS_UNAVAILABLE
#define DROPUS_UNAVAILABLE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:153
DROPUS_DIRECTORY_NOT_EMPTY
#define DROPUS_DIRECTORY_NOT_EMPTY
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:147
dropus_int32
int32_t dropus_int32
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:56
NULL
#define NULL
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:72
dropus_init_file_w
DROPUS_API dropus_result dropus_init_file_w(dropus *pOpus, const wchar_t *pFilePath, const dropus_allocation_callbacks *pAllocationCallbacks)
DROPUS_PATH_TOO_LONG
#define DROPUS_PATH_TOO_LONG
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:143
dropus_malloc
DROPUS_API void * dropus_malloc(size_t sz, const dropus_allocation_callbacks *pAllocationCallbacks)
DROPUS_NO_SPACE
#define DROPUS_NO_SPACE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:149
DROPUS_END_OF_FILE
#define DROPUS_END_OF_FILE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:148
errno
int errno
dropus::onSeek
dropus_seek_proc onSeek
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:264
DROPUS_PROTOCOL_UNAVAILABLE
#define DROPUS_PROTOCOL_UNAVAILABLE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:171
dropus_stream_frame
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:206
dropus_mode
dropus_mode
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:199
DROPUS_NO_ADDRESS
#define DROPUS_NO_ADDRESS
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:169
dropus_bool32
dropus_uint32 dropus_bool32
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:63
dropus_allocation_callbacks::onFree
void(* onFree)(void *p, void *pUserData)
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:258
DROPUS_NO_DATA_AVAILABLE
#define DROPUS_NO_DATA_AVAILABLE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:163
DROPUS_ALREADY_IN_USE
#define DROPUS_ALREADY_IN_USE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:154
dropus::pFile
void * pFile
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:267
dropus_stream_packet
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:211
dropus_stream
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:217
DROPUS_CRC_MISMATCH
#define DROPUS_CRC_MISMATCH
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:185
dropus_int16
int16_t dropus_int16
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:54
dropus_stream::w1_Q13_prev
dropus_int32 w1_Q13_prev
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:223
DROPUS_INVALID_DATA
#define DROPUS_INVALID_DATA
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:164
dropus_allocation_callbacks::onMalloc
void *(* onMalloc)(size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:256
DROPUS_NOT_UNIQUE
#define DROPUS_NOT_UNIQUE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:167
dropus_int8
int8_t dropus_int8
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:52
DROPUS_SUCCESS
#define DROPUS_SUCCESS
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:131
DROPUS_SOCKET_NOT_SUPPORTED
#define DROPUS_SOCKET_NOT_SUPPORTED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:175
DROPUS_TRUE
#define DROPUS_TRUE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:64
DROPUS_DEADLOCK
#define DROPUS_DEADLOCK
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:158
dropus_stream::packet
dropus_stream_packet packet
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:219
dropus::currentReadPos
size_t currentReadPos
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:272
f
f
DROPUS_NAME_TOO_LONG
#define DROPUS_NAME_TOO_LONG
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:144
DROPUS_BAD_ADDRESS
#define DROPUS_BAD_ADDRESS
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:155
dropus_seek_origin
dropus_seek_origin
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:244
DROPUS_BAD_MESSAGE
#define DROPUS_BAD_MESSAGE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:162
DROPUS_ERROR
#define DROPUS_ERROR
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:132
dropus_seek_proc
dropus_bool32(* dropus_seek_proc)(void *pUserData, int offset, dropus_seek_origin origin)
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:251
DROPUS_NOT_CONNECTED
#define DROPUS_NOT_CONNECTED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:178
dropus_stream_packet::toc
dropus_uint8 toc
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:213
DROPUS_BAD_SEEK
#define DROPUS_BAD_SEEK
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:156
dropus::allocationCallbacks
dropus_allocation_callbacks allocationCallbacks
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:266
dropus_free
DROPUS_API void dropus_free(void *p, const dropus_allocation_callbacks *pAllocationCallbacks)
DROPUS_API
#define DROPUS_API
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:125
dropus_realloc
DROPUS_API void * dropus_realloc(void *p, size_t sz, const dropus_allocation_callbacks *pAllocationCallbacks)
DROPUS_PROTOCOL_NOT_SUPPORTED
#define DROPUS_PROTOCOL_NOT_SUPPORTED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:172
dropus_seek_origin_start
@ dropus_seek_origin_start
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:250
DROPUS_IN_PROGRESS
#define DROPUS_IN_PROGRESS
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:181
DROPUS_NOT_SOCKET
#define DROPUS_NOT_SOCKET
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:168
dropus_uintptr
uintptr_t dropus_uintptr
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:60
DROPUS_MAX_OPUS_FRAMES_PER_PACKET
#define DROPUS_MAX_OPUS_FRAMES_PER_PACKET
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:196
dropus_init_memory
DROPUS_API dropus_result dropus_init_memory(dropus *pOpus, const void *pData, size_t dataSize, const dropus_allocation_callbacks *pAllocationCallbacks)
dropus_stream::silk
struct dropus_stream::@131 silk
dropus_stream_init
DROPUS_API dropus_result dropus_stream_init(dropus_stream *pOpusStream)
dropus
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:261
DROPUS_ACCESS_DENIED
#define DROPUS_ACCESS_DENIED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:137
DROPUS_OUT_OF_RANGE
#define DROPUS_OUT_OF_RANGE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:136
DROPUS_NO_HOST
#define DROPUS_NO_HOST
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:180
dropus_uint16
uint16_t dropus_uint16
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:55
dropus_init_file
DROPUS_API dropus_result dropus_init_file(dropus *pOpus, const char *pFilePath, const dropus_allocation_callbacks *pAllocationCallbacks)
DROPUS_IS_DIRECTORY
#define DROPUS_IS_DIRECTORY
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:146
dropus::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:265
DROPUS_NO_MESSAGE
#define DROPUS_NO_MESSAGE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:161
dropus_mode_hybrid
@ dropus_mode_hybrid
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:203
DROPUS_BAD_DATA
#define DROPUS_BAD_DATA
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:186
dropus_stream_frame::sizeInBytes
dropus_uint16 sizeInBytes
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:208
DROPUS_ALREADY_CONNECTED
#define DROPUS_ALREADY_CONNECTED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:177
DROPUS_TIMEOUT
#define DROPUS_TIMEOUT
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:165
L
#define L
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/stb_vorbis.c:5102
DROPUS_AT_END
#define DROPUS_AT_END
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:184
dropus_result_description
const DROPUS_API char * dropus_result_description(dropus_result result)
DROPUS_BUSY
#define DROPUS_BUSY
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:150
dropus_init
DROPUS_API dropus_result dropus_init(dropus *pOpus, dropus_read_proc onRead, dropus_seek_proc onSeek, void *pUserData, const dropus_allocation_callbacks *pAllocationCallbacks)
DROPUS_PROTOCOL_FAMILY_NOT_SUPPORTED
#define DROPUS_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:173
DROPUS_ADDRESS_FAMILY_NOT_SUPPORTED
#define DROPUS_ADDRESS_FAMILY_NOT_SUPPORTED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:174
DROPUS_INLINE
#define DROPUS_INLINE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:97
dropus_proc
void(* dropus_proc)(void)
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:69
dropus_uninit
DROPUS_API void dropus_uninit(dropus *pOpus)
dropus_handle
void * dropus_handle
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:67
DROPUS_INVALID_FILE
#define DROPUS_INVALID_FILE
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:141
dropus_ptr
void * dropus_ptr
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:68
DROPUS_CONNECTION_REFUSED
#define DROPUS_CONNECTION_REFUSED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:179
dropus_uint8
uint8_t dropus_uint8
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:53
dropus_int64
int64_t dropus_int64
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:58
DROPUS_DOES_NOT_EXIST
#define DROPUS_DOES_NOT_EXIST
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:138
dropus_stream_packet::frames
dropus_stream_frame frames[DROPUS_MAX_OPUS_FRAMES_PER_PACKET]
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:214
DROPUS_ALREADY_EXISTS
#define DROPUS_ALREADY_EXISTS
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:139
dropus_mode_silk
@ dropus_mode_silk
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:201
dropus_uint8
uint8_t dropus_uint8
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:53
dropus_int16
int16_t dropus_int16
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:54
dropus_mode_celt
@ dropus_mode_celt
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:202
DROPUS_IO_ERROR
#define DROPUS_IO_ERROR
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:151
dropus::pData
const dropus_uint8 * pData
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:270
DROPUS_TOO_MANY_OPEN_FILES
#define DROPUS_TOO_MANY_OPEN_FILES
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:140
DROPUS_OUT_OF_MEMORY
#define DROPUS_OUT_OF_MEMORY
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:135
dropus_allocation_callbacks::onRealloc
void *(* onRealloc)(void *p, size_t sz, void *pUserData)
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:257
DROPUS_BAD_PROTOCOL
#define DROPUS_BAD_PROTOCOL
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:170
dropus_uintptr
uintptr_t dropus_uintptr
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:60
dropus_int32
int32_t dropus_int32
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:56
DROPUS_INTERRUPT
#define DROPUS_INTERRUPT
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:152
dropus_uint32
uint32_t dropus_uint32
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:57
config
static sai_transceiver_t config
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:75
dropus_uint64
uint64_t dropus_uint64
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:59
dropus_allocation_callbacks::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:255
dropus::onRead
dropus_read_proc onRead
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:263
DROPUS_NOT_DIRECTORY
#define DROPUS_NOT_DIRECTORY
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:145
dropus_stream::w0_Q13_prev
dropus_int32 w0_Q13_prev
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:222
assert.h
DROPUS_MEMORY_ALREADY_MAPPED
#define DROPUS_MEMORY_ALREADY_MAPPED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:183
DROPUS_NO_NETWORK
#define DROPUS_NO_NETWORK
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:166
dropus_result
int dropus_result
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:130
DROPUS_NOT_IMPLEMENTED
#define DROPUS_NOT_IMPLEMENTED
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:160
dropus::memory
struct dropus::@132 memory
DROPUS_INVALID_ARGS
#define DROPUS_INVALID_ARGS
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:133
dropus_uint64
uint64_t dropus_uint64
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:59
dropus_result
int dropus_result
Definition: porcupine/demo/c/dr_libs/wip/dr_opus.h:130
dropus_read_proc
size_t(* dropus_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:250
dropus_bool8
dropus_uint8 dropus_bool8
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:62
DROPUS_CONNECTION_RESET
#define DROPUS_CONNECTION_RESET
Definition: rhino/demo/c/dr_libs/wip/dr_opus.h:176


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