forked from KolibriOS/kolibrios
STB_Vorbis - OGG Vorbis decoder
git-svn-id: svn://kolibrios.org@8039 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
e8a367619a
commit
22c37f1c0b
10
contrib/media/stb_vorbis/Tupfile.lua
Normal file
10
contrib/media/stb_vorbis/Tupfile.lua
Normal file
@ -0,0 +1,10 @@
|
||||
if tup.getconfig("NO_GCC") ~= "" then return end
|
||||
if tup.getconfig("HELPERDIR") == ""
|
||||
then
|
||||
HELPERDIR = "../../../programs"
|
||||
end
|
||||
tup.include(HELPERDIR .. "/use_gcc.lua")
|
||||
NEWLIB_INCLUDE = "../../sdk/sources/newlib/libc/include"
|
||||
INCLUDES = INCLUDES .. " -I" .. NEWLIB_INCLUDE
|
||||
CFLAGS = CFLAGS_OPTIMIZE_SPEED .. " -nostdlib -fwhole-program"
|
||||
compile_gcc("libvorbis.c", "stb_vorbis.obj")
|
3
contrib/media/stb_vorbis/compile kolibrios lib.bat
Normal file
3
contrib/media/stb_vorbis/compile kolibrios lib.bat
Normal file
@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
gcc -c libvorbis.c -o stb_vorbis.obj -O3 -march=i586 -mfpmath=387 -ffast-math -fwhole-program -nostdlib
|
||||
pause
|
103
contrib/media/stb_vorbis/libvorbis.c
Normal file
103
contrib/media/stb_vorbis/libvorbis.c
Normal file
@ -0,0 +1,103 @@
|
||||
// OGG vorbis for KolibriOS in native shared COFF library format.
|
||||
|
||||
// https://github.com/nothings/stb/blob/master/stb_vorbis.c
|
||||
|
||||
// Some functions to allow us building without any external libs
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void* memset(void *base, int val, size_t len)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < len; ++i) ((char *) base)[i] = val;
|
||||
}
|
||||
|
||||
int memcmp(const void *p1, const void *p2, size_t len)
|
||||
{
|
||||
unsigned char *q1 = (unsigned char *) p1;
|
||||
unsigned char *q2 = (unsigned char *) p2;
|
||||
int i;
|
||||
for (i=0; i < len; ++i)
|
||||
if (q1[i] < q2[i]) return -1;
|
||||
else if (q1[i] > q2[i]) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* memcpy(void *dest, const void *src, size_t num)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < num; ++i)
|
||||
((char *)dest)[i] = ((char *) src)[i];
|
||||
}
|
||||
|
||||
double powerd (double x, int y)
|
||||
{
|
||||
double temp;
|
||||
if (y == 0)
|
||||
return 1;
|
||||
temp = powerd (x, y / 2);
|
||||
if ((y % 2) == 0) {
|
||||
return temp * temp;
|
||||
} else {
|
||||
if (y > 0)
|
||||
return x * temp * temp;
|
||||
else
|
||||
return (temp * temp) / x;
|
||||
}
|
||||
}
|
||||
|
||||
double ldexp(double Value, int Exponent)
|
||||
{
|
||||
return((Value * powerd(2.0, Exponent)));
|
||||
}
|
||||
|
||||
#include "qsort.c"
|
||||
|
||||
// For building with mingw compiler
|
||||
__attribute__((externally_visible)) void __chkstk_ms(){
|
||||
return;
|
||||
}
|
||||
|
||||
# define assert(expr) ((void) (0))
|
||||
|
||||
// Actual stb_vorbis related stuff starts here
|
||||
|
||||
#define STB_VORBIS_NO_STDIO 1
|
||||
#define STB_VORBIS_NO_CRT 1
|
||||
//#define STB_VORBIS_NO_PULLDATA_API 1
|
||||
|
||||
#include "stb_vorbis.c"
|
||||
|
||||
// KolibriOS type EXPORTS header
|
||||
|
||||
int __stdcall libInit(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
char *name;
|
||||
void *f;
|
||||
}export_t;
|
||||
|
||||
char szLibInit[] ="lib_init";
|
||||
char szVersion[] ="version";
|
||||
char szPushDataOpen[] ="pushdata_open";
|
||||
char szPushDataDecode[] ="pushdata_decode";
|
||||
char szPushDataFlush[] ="pushdata_flush";
|
||||
//char szConvertSamplesShort[] = "convert_samples_short";
|
||||
char szConvertSamplesShortInterleaved[] = "convert_channels_short_interleaved";
|
||||
|
||||
__attribute__((externally_visible)) export_t EXPORTS[] __asm__("EXPORTS") =
|
||||
{
|
||||
{ szLibInit, libInit },
|
||||
{ szVersion, (void*)0x00010001 },
|
||||
{ szPushDataOpen, stb_vorbis_open_pushdata },
|
||||
{ szPushDataDecode, stb_vorbis_decode_frame_pushdata },
|
||||
{ szPushDataFlush, stb_vorbis_flush_pushdata},
|
||||
//{ szConvertSamplesShort, convert_samples_short},
|
||||
{ szConvertSamplesShortInterleaved, convert_channels_short_interleaved},
|
||||
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
// End of file
|
252
contrib/media/stb_vorbis/qsort.c
Normal file
252
contrib/media/stb_vorbis/qsort.c
Normal file
@ -0,0 +1,252 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Author: Remi Dufour - remi.dufour@gmail.com
|
||||
* Date: July 23rd, 2012
|
||||
*
|
||||
* Name: Quicksort
|
||||
*
|
||||
* Description: This is a well-known sorting algorithm developed by C. A. R.
|
||||
* Hoare. It is a comparison sort and in this implementation,
|
||||
* is not a stable sort.
|
||||
*
|
||||
* Note: This is public-domain C implementation written from
|
||||
* scratch. Use it at your own risk.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Insertion sort threshold shift
|
||||
*
|
||||
* This macro defines the threshold shift (power of 2) at which the insertion
|
||||
* sort algorithm replaces the Quicksort. A zero threshold shift disables the
|
||||
* insertion sort completely.
|
||||
*
|
||||
* The value is optimized for Linux and MacOS on the Intel x86 platform.
|
||||
*/
|
||||
#ifndef INSERTION_SORT_THRESHOLD_SHIFT
|
||||
# ifdef __APPLE__ & __MACH__
|
||||
# define INSERTION_SORT_THRESHOLD_SHIFT 0
|
||||
# else
|
||||
# define INSERTION_SORT_THRESHOLD_SHIFT 2
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Macro SWAP
|
||||
*
|
||||
* Swaps the elements of two arrays.
|
||||
*
|
||||
* The length of the swap is determined by the value of "SIZE". While both
|
||||
* arrays can't overlap, the case in which both pointers are the same works.
|
||||
*/
|
||||
#define SWAP(A,B,SIZE) \
|
||||
{ \
|
||||
register char *a_byte = A; \
|
||||
register char *b_byte = B; \
|
||||
register const char *a_end = a_byte + SIZE; \
|
||||
\
|
||||
while (a_byte < a_end) \
|
||||
{ \
|
||||
register const char swap_byte = *b_byte; \
|
||||
*b_byte++ = *a_byte; \
|
||||
*a_byte++ = swap_byte; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Macro SWAP_NEXT
|
||||
*
|
||||
* Swaps the elements of an array with its next value.
|
||||
*
|
||||
* The length of the swap is determined by the value of "SIZE". This macro
|
||||
* must be used at the beginning of a scope and "A" shouldn't be an expression.
|
||||
*/
|
||||
#define SWAP_NEXT(A,SIZE) \
|
||||
register char *a_byte = A; \
|
||||
register const char *a_end = A + SIZE; \
|
||||
\
|
||||
while (a_byte < a_end) \
|
||||
{ \
|
||||
register const char swap_byte = *(a_byte + SIZE); \
|
||||
*(a_byte + SIZE) = *a_byte; \
|
||||
*a_byte++ = swap_byte; \
|
||||
}
|
||||
|
||||
/* Function Quicksort
|
||||
*
|
||||
* This function performs a basic Quicksort. This implementation is the
|
||||
* in-place version of the algorithm and is done in he following way:
|
||||
*
|
||||
* 1. In the middle of the array, we determine a pivot that we temporarily swap
|
||||
* to the end.
|
||||
* 2. From the beginning to the end of the array, we swap any elements smaller
|
||||
* than this pivot to the start, adjacent to other elements that were
|
||||
* already moved.
|
||||
* 3. We swap the pivot next to these smaller elements.
|
||||
* 4. For both sub-arrays on sides of the pivot, we repeat this process
|
||||
* recursively.
|
||||
* 5. For a sub-array smaller than a certain threshold, the insertion sort
|
||||
* algorithm takes over.
|
||||
*
|
||||
* As an optimization, rather than performing a real recursion, we keep a
|
||||
* global stack to track boundaries for each recursion level.
|
||||
*
|
||||
* To ensure that at most O(log2 N) space is used, we recurse into the smaller
|
||||
* partition first. The log2 of the highest unsigned value of an integer type
|
||||
* is the number of bits needed to store that integer.
|
||||
*/
|
||||
void qsort(void *array,
|
||||
size_t length,
|
||||
size_t size,
|
||||
int(*compare)(const void *, const void *))
|
||||
{
|
||||
/* Recursive stacks for array boundaries (both inclusive) */
|
||||
struct stackframe
|
||||
{
|
||||
void *left;
|
||||
void *right;
|
||||
} stack[CHAR_BIT * sizeof(void *)];
|
||||
|
||||
/* Recursion level */
|
||||
struct stackframe *recursion = stack;
|
||||
|
||||
#if INSERTION_SORT_THRESHOLD_SHIFT != 0
|
||||
/* Insertion sort threshold */
|
||||
const int threshold = size << INSERTION_SORT_THRESHOLD_SHIFT;
|
||||
#endif
|
||||
|
||||
/* Assign the first recursion level of the sorting */
|
||||
recursion->left = array;
|
||||
recursion->right = (char *)array + size * (length - 1);
|
||||
|
||||
do
|
||||
{
|
||||
/* Partition the array */
|
||||
register char *index = recursion->left;
|
||||
register char *right = recursion->right;
|
||||
char *left = index;
|
||||
|
||||
/* Assigning store to the left */
|
||||
register char *store = index;
|
||||
|
||||
/* Pop the stack */
|
||||
--recursion;
|
||||
|
||||
/* Determine a pivot (in the middle) and move it to the end */
|
||||
const size_t middle = (right - left) >> 1;
|
||||
SWAP(left + middle - middle % size,right,size)
|
||||
|
||||
/* From left to right */
|
||||
while (index < right)
|
||||
{
|
||||
/* If item is smaller than pivot */
|
||||
if (compare(right, index) > 0)
|
||||
{
|
||||
/* Swap item and store */
|
||||
SWAP(index,store,size)
|
||||
|
||||
/* We increment store */
|
||||
store += size;
|
||||
}
|
||||
|
||||
index += size;
|
||||
}
|
||||
|
||||
/* Move the pivot to its final place */
|
||||
SWAP(right,store,size)
|
||||
|
||||
/* Performs a recursion to the left */
|
||||
#define RECURSE_LEFT \
|
||||
if (left < store - size) \
|
||||
{ \
|
||||
(++recursion)->left = left; \
|
||||
recursion->right = store - size; \
|
||||
}
|
||||
|
||||
/* Performs a recursion to the right */
|
||||
#define RECURSE_RIGHT \
|
||||
if (store + size < right) \
|
||||
{ \
|
||||
(++recursion)->left = store + size; \
|
||||
recursion->right = right; \
|
||||
}
|
||||
|
||||
/* Insertion sort inner-loop */
|
||||
#define INSERTION_SORT_LOOP(LEFT) \
|
||||
{ \
|
||||
register char *trail = index - size; \
|
||||
while (trail >= LEFT && compare(trail, trail + size) > 0) \
|
||||
{ \
|
||||
SWAP_NEXT(trail,size) \
|
||||
trail -= size; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Performs insertion sort left of the pivot */
|
||||
#define INSERTION_SORT_LEFT \
|
||||
for (index = left + size; index < store; index +=size) \
|
||||
INSERTION_SORT_LOOP(left)
|
||||
|
||||
/* Performs insertion sort right of the pivot */
|
||||
#define INSERTION_SORT_RIGHT \
|
||||
for (index = store + (size << 1); index <= right; index +=size) \
|
||||
INSERTION_SORT_LOOP(store + size)
|
||||
|
||||
/* Sorts to the left */
|
||||
#if INSERTION_SORT_THRESHOLD_SHIFT == 0
|
||||
# define SORT_LEFT RECURSE_LEFT
|
||||
#else
|
||||
# define SORT_LEFT \
|
||||
if (store - left <= threshold) \
|
||||
{ \
|
||||
INSERTION_SORT_LEFT \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RECURSE_LEFT \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sorts to the right */
|
||||
#if INSERTION_SORT_THRESHOLD_SHIFT == 0
|
||||
# define SORT_RIGHT RECURSE_RIGHT
|
||||
#else
|
||||
# define SORT_RIGHT \
|
||||
if (right - store <= threshold) \
|
||||
{ \
|
||||
INSERTION_SORT_RIGHT \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
RECURSE_RIGHT \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Recurse into the smaller partition first */
|
||||
if (store - left < right - store)
|
||||
{
|
||||
/* Left side is smaller */
|
||||
SORT_RIGHT
|
||||
SORT_LEFT
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Right side is smaller */
|
||||
SORT_LEFT
|
||||
SORT_RIGHT
|
||||
|
||||
#undef RECURSE_LEFT
|
||||
#undef RECURSE_RIGHT
|
||||
#undef INSERTION_SORT_LOOP
|
||||
#undef INSERTION_SORT_LEFT
|
||||
#undef INSERTION_SORT_RIGHT
|
||||
#undef SORT_LEFT
|
||||
#undef SORT_RIGHT
|
||||
}
|
||||
while (recursion >= stack);
|
||||
}
|
||||
|
||||
#undef INSERTION_SORT_THRESHOLD_SHIFT
|
||||
#undef SWAP
|
||||
#undef SWAP_NEXT
|
5555
contrib/media/stb_vorbis/stb_vorbis.c
Normal file
5555
contrib/media/stb_vorbis/stb_vorbis.c
Normal file
File diff suppressed because it is too large
Load Diff
38
contrib/media/stb_vorbis/stb_vorbis.inc
Normal file
38
contrib/media/stb_vorbis/stb_vorbis.inc
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
struc vorb_alloc_buffer {
|
||||
|
||||
.ptr dd ?
|
||||
.length dd ?
|
||||
|
||||
}
|
||||
|
||||
struc stb_vorbis_info {
|
||||
|
||||
.sample_rate dd ? ; unsigned int
|
||||
.channels dd ? ; signed int
|
||||
|
||||
.setup_memory_required dd ?
|
||||
.setup_temp_memory_required dd ?
|
||||
.temp_memory_required dd ?
|
||||
|
||||
.max_frame_size dd ?
|
||||
|
||||
}
|
||||
|
||||
; invoke pushdata_open, input_buf, [buf_size], consumed, error, alloc_buffer
|
||||
; test eax, eax
|
||||
; jz
|
||||
; mov [vorb], eax
|
||||
|
||||
; invoke pushdata_decode, [vorb], input_buf, [buf_size], numchannels, float_samples, numsamples
|
||||
; mov [bytes_consumed], eax
|
||||
|
||||
; invoke vorb_convert_channels_short_interleaved, numchannels, pcm, numchannels, float_samples, int d_offset, int len
|
||||
|
||||
;consumed dd ?
|
||||
;error dd ?
|
||||
;numchannels dd ?
|
||||
;numsamples dd ?
|
||||
;float_samples rd ?
|
||||
;pcm rw VORB_MAX_SAMPLES_PER_FRAME
|
||||
|
Loading…
Reference in New Issue
Block a user