mirror of
https://github.com/libretro/retroluxury.git
synced 2024-11-23 07:39:47 +00:00
too much things to enumerate...
This commit is contained in:
parent
c2443374e4
commit
3bbe3424cd
9
.gitignore
vendored
9
.gitignore
vendored
@ -2,6 +2,15 @@
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.png
|
||||
*.tmx
|
||||
*.tsx
|
||||
*~
|
||||
rl_version.c
|
||||
boot_lua.h
|
||||
bounce.h
|
||||
sketch008.h
|
||||
smile.h
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
|
@ -4,7 +4,7 @@ DEFINES=-DOUTSIDE_SPEEX -DRANDOM_PREFIX=speex -DEXPORT= -DFIXED_POINT
|
||||
#CFLAGS=-O3 --std=c99 -Wall $(INCLUDES) $(DEFINES) -fPIC
|
||||
CFLAGS=-O0 -g --std=c99 -Wall $(INCLUDES) $(DEFINES) -fPIC
|
||||
|
||||
OBJS=rl_backgrnd.o rl_base64.o rl_config.o rl_image.o rl_imgdata.o rl_pack.o rl_rand.o rl_resample.o rl_sound.o rl_snddata.o rl_sprite.o rl_version.o rl_xml.o external/resample.o
|
||||
OBJS=rl_backgrnd.o rl_base64.o rl_config.o rl_image.o rl_imgdata.o rl_pack.o rl_rand.o rl_resample.o rl_sound.o rl_snddata.o rl_sprite.o rl_tiled.o rl_version.o rl_xml.o external/resample.o
|
||||
|
||||
%.o: %.c
|
||||
gcc $(CFLAGS) -c $< -o $@
|
||||
|
@ -7,7 +7,8 @@
|
||||
//#define RL_BACKGRND_STRETCH 1
|
||||
//#define RL_BACKGRND_EXPAND 2
|
||||
|
||||
#define RL_COLOR( r, g, b ) ( ( r * 32 / 256 ) << 11 | ( g * 64 / 256 ) << 5 | ( b * 32 / 256 ) )
|
||||
#define RL_COLOR( r, g, b ) ( ( ( r ) * 32 / 256 ) << 11 | ( ( g ) * 64 / 256 ) << 5 | ( ( b ) * 32 / 256 ) )
|
||||
#define RL_COLOR_2( rgb ) RL_COLOR( ( rgb >> 16 ) & 255, ( rgb >> 8 ) & 255, rgb & 255 )
|
||||
|
||||
int rl_backgrnd_create( int width, int height, int aspect );
|
||||
void rl_backgrnd_destroy( void );
|
||||
|
@ -1,27 +1,27 @@
|
||||
#include <rl_config.h>
|
||||
|
||||
static const rl_config_t config =
|
||||
{
|
||||
RL_VERSION_MAJOR,
|
||||
RL_VERSION_MINOR,
|
||||
RL_BACKGRND_MARGIN,
|
||||
RL_MAX_SPRITES,
|
||||
RL_BG_SAVE_SIZE,
|
||||
RL_FRAME_RATE,
|
||||
RL_SAMPLE_RATE,
|
||||
RL_SAMPLES_PER_FRAME,
|
||||
RL_RESAMPLER_QUALITY,
|
||||
RL_MAX_VOICES,
|
||||
RL_OGG_INCREMENT,
|
||||
#ifdef RL_OGG_VORBIS
|
||||
1,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
RL_USERDATA_COUNT
|
||||
};
|
||||
|
||||
const rl_config_t* rl_get_config( void )
|
||||
{
|
||||
return &config;
|
||||
}
|
||||
#include <rl_config.h>
|
||||
|
||||
static const rl_config_t config =
|
||||
{
|
||||
RL_VERSION_MAJOR,
|
||||
RL_VERSION_MINOR,
|
||||
RL_BACKGRND_MARGIN,
|
||||
RL_MAX_SPRITES,
|
||||
RL_BG_SAVE_SIZE,
|
||||
RL_FRAME_RATE,
|
||||
RL_SAMPLE_RATE,
|
||||
RL_SAMPLES_PER_FRAME,
|
||||
RL_RESAMPLER_QUALITY,
|
||||
RL_MAX_VOICES,
|
||||
RL_OGG_INCREMENT,
|
||||
#ifdef RL_OGG_VORBIS
|
||||
1,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
RL_USERDATA_COUNT
|
||||
};
|
||||
|
||||
const rl_config_t* rl_get_config( void )
|
||||
{
|
||||
return &config;
|
||||
}
|
||||
|
@ -10,3 +10,16 @@ static inline uint32_t djb2( const char* str )
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static inline uint32_t djb2_length( const char* str, size_t length )
|
||||
{
|
||||
const unsigned char* aux = (const unsigned char*)str;
|
||||
uint32_t hash = 5381;
|
||||
|
||||
while ( length-- )
|
||||
{
|
||||
hash = ( hash << 5 ) + hash + *aux++;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <rl_imgdata.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
An image with RLE-encoded pixels and per-pixel alpha of 0, 25, 50, 75 and 100%.
|
||||
|
@ -1,86 +1,86 @@
|
||||
#include <rl_resample.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "external/speex_resampler.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#if RL_RESAMPLER_QUALITY < SPEEX_RESAMPLER_QUALITY_MIN || RL_RESAMPLER_QUALITY > SPEEX_RESAMPLER_QUALITY_MAX
|
||||
#error Invalid quality value in RL_RESAMPLER_QUALITY
|
||||
#endif
|
||||
|
||||
static char passthrough = 0;
|
||||
|
||||
rl_resampler_t* rl_resampler_create( unsigned in_freq )
|
||||
{
|
||||
if ( in_freq != RL_SAMPLE_RATE )
|
||||
{
|
||||
return (rl_resampler_t*)speex_resampler_init( 2, in_freq, RL_SAMPLE_RATE, RL_RESAMPLER_QUALITY, NULL );
|
||||
}
|
||||
|
||||
return (rl_resampler_t*)&passthrough;
|
||||
}
|
||||
|
||||
void rl_resampler_destroy( rl_resampler_t* resampler )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
speex_resampler_destroy( (SpeexResamplerState*)resampler );
|
||||
}
|
||||
}
|
||||
|
||||
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
|
||||
spx_uint32_t in_rate, out_rate;
|
||||
|
||||
speex_resampler_get_rate( st, &in_rate, &out_rate );
|
||||
return in_samples * out_rate / in_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return in_samples;
|
||||
}
|
||||
}
|
||||
|
||||
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
|
||||
spx_uint32_t in_rate, out_rate;
|
||||
|
||||
speex_resampler_get_rate( st, &in_rate, &out_rate );
|
||||
return out_samples * in_rate / out_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return out_samples;
|
||||
}
|
||||
}
|
||||
|
||||
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
spx_uint32_t in_len = in_samples;
|
||||
spx_uint32_t out_len = out_samples;
|
||||
|
||||
int error = speex_resampler_process_int( (SpeexResamplerState*)resampler, 0, in_buffer, &in_len, out_buffer, &out_len );
|
||||
return error == RESAMPLER_ERR_SUCCESS ? out_len : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( in_samples > out_samples )
|
||||
{
|
||||
in_samples = out_samples;
|
||||
}
|
||||
|
||||
memcpy( out_buffer, in_buffer, in_samples * sizeof( int16_t ) );
|
||||
return in_samples;
|
||||
}
|
||||
}
|
||||
#include <rl_resample.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "external/speex_resampler.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#if RL_RESAMPLER_QUALITY < SPEEX_RESAMPLER_QUALITY_MIN || RL_RESAMPLER_QUALITY > SPEEX_RESAMPLER_QUALITY_MAX
|
||||
#error Invalid quality value in RL_RESAMPLER_QUALITY
|
||||
#endif
|
||||
|
||||
static char passthrough = 0;
|
||||
|
||||
rl_resampler_t* rl_resampler_create( unsigned in_freq )
|
||||
{
|
||||
if ( in_freq != RL_SAMPLE_RATE )
|
||||
{
|
||||
return (rl_resampler_t*)speex_resampler_init( 2, in_freq, RL_SAMPLE_RATE, RL_RESAMPLER_QUALITY, NULL );
|
||||
}
|
||||
|
||||
return (rl_resampler_t*)&passthrough;
|
||||
}
|
||||
|
||||
void rl_resampler_destroy( rl_resampler_t* resampler )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
speex_resampler_destroy( (SpeexResamplerState*)resampler );
|
||||
}
|
||||
}
|
||||
|
||||
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
|
||||
spx_uint32_t in_rate, out_rate;
|
||||
|
||||
speex_resampler_get_rate( st, &in_rate, &out_rate );
|
||||
return in_samples * out_rate / in_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return in_samples;
|
||||
}
|
||||
}
|
||||
|
||||
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
SpeexResamplerState* st = (SpeexResamplerState*)resampler;
|
||||
spx_uint32_t in_rate, out_rate;
|
||||
|
||||
speex_resampler_get_rate( st, &in_rate, &out_rate );
|
||||
return out_samples * in_rate / out_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return out_samples;
|
||||
}
|
||||
}
|
||||
|
||||
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples )
|
||||
{
|
||||
if ( resampler != (rl_resampler_t*)&passthrough )
|
||||
{
|
||||
spx_uint32_t in_len = in_samples;
|
||||
spx_uint32_t out_len = out_samples;
|
||||
|
||||
int error = speex_resampler_process_int( (SpeexResamplerState*)resampler, 0, in_buffer, &in_len, out_buffer, &out_len );
|
||||
return error == RESAMPLER_ERR_SUCCESS ? out_len : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( in_samples > out_samples )
|
||||
{
|
||||
in_samples = out_samples;
|
||||
}
|
||||
|
||||
memcpy( out_buffer, in_buffer, in_samples * sizeof( int16_t ) );
|
||||
return in_samples;
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
#ifndef RL_RESAMPLE_H
|
||||
#define RL_RESAMPLE_H
|
||||
|
||||
#include <rl_userdata.h>
|
||||
#include <rl_imgdata.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void rl_resampler_t;
|
||||
|
||||
/* Creates a resampler. */
|
||||
rl_resampler_t* rl_resampler_create( unsigned in_freq );
|
||||
/* Destroys a resampler. */
|
||||
void rl_resampler_destroy( rl_resampler_t* resampler );
|
||||
|
||||
/* Returns how much samples an output buffer must have to resample an input buffer with this number of samples. */
|
||||
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples );
|
||||
/* Returns how much samples an input buffer must have to fill an output buffer with this number of samples. */
|
||||
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples );
|
||||
/* Resamples the input buffer into the output buffer. */
|
||||
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples );
|
||||
|
||||
#endif /* RL_RESAMPLE_H */
|
||||
#ifndef RL_RESAMPLE_H
|
||||
#define RL_RESAMPLE_H
|
||||
|
||||
#include <rl_userdata.h>
|
||||
#include <rl_imgdata.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void rl_resampler_t;
|
||||
|
||||
/* Creates a resampler. */
|
||||
rl_resampler_t* rl_resampler_create( unsigned in_freq );
|
||||
/* Destroys a resampler. */
|
||||
void rl_resampler_destroy( rl_resampler_t* resampler );
|
||||
|
||||
/* Returns how much samples an output buffer must have to resample an input buffer with this number of samples. */
|
||||
size_t rl_resampler_out_samples( rl_resampler_t* resampler, size_t in_samples );
|
||||
/* Returns how much samples an input buffer must have to fill an output buffer with this number of samples. */
|
||||
size_t rl_resampler_in_samples( rl_resampler_t* resampler, size_t out_samples );
|
||||
/* Resamples the input buffer into the output buffer. */
|
||||
size_t rl_resampler_resample( rl_resampler_t* resampler, const int16_t* in_buffer, size_t in_samples, int16_t* out_buffer, size_t out_samples );
|
||||
|
||||
#endif /* RL_RESAMPLE_H */
|
||||
|
450
src/rl_snddata.c
450
src/rl_snddata.c
@ -1,225 +1,225 @@
|
||||
#include <rl_snddata.h>
|
||||
#include <rl_resample.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rl_endian.inl>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* header */
|
||||
char chunkid[ 4 ];
|
||||
uint32_t chunksize;
|
||||
char format[ 4 ];
|
||||
/* fmt */
|
||||
char subchunk1id[ 4 ];
|
||||
uint32_t subchunk1size;
|
||||
uint16_t audioformat;
|
||||
uint16_t numchannels;
|
||||
uint32_t samplerate;
|
||||
uint32_t byterate;
|
||||
uint16_t blockalign;
|
||||
uint16_t bitspersample;
|
||||
/* data */
|
||||
char subchunk2id[ 4 ];
|
||||
uint32_t subchunk2size;
|
||||
uint8_t data[ 0 ];
|
||||
|
||||
}
|
||||
wave_t;
|
||||
|
||||
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size )
|
||||
{
|
||||
const wave_t* wave = (const wave_t*)data;
|
||||
|
||||
if ( wave->chunkid[ 0 ] != 'R' || wave->chunkid[ 1 ] != 'I' || wave->chunkid[ 2 ] != 'F' || wave->chunkid[ 3 ] != 'F' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( wave->format[ 0 ] != 'W' || wave->format[ 1 ] != 'A' || wave->format[ 2 ] != 'V' || wave->format[ 3 ] != 'E' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( wave->subchunk1id[ 0 ] != 'f' || wave->subchunk1id[ 1 ] != 'm' || wave->subchunk1id[ 2 ] != 't' || wave->subchunk1id[ 3 ] != ' ' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( wave->subchunk2id[ 0 ] != 'd' || wave->subchunk2id[ 1 ] != 'a' || wave->subchunk2id[ 2 ] != 't' || wave->subchunk2id[ 3 ] != 'a' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
snddata->bps = le16( wave->bitspersample );
|
||||
snddata->channels = le16( wave->numchannels );
|
||||
snddata->freq = le32( wave->samplerate );
|
||||
|
||||
if ( le16( wave->audioformat ) != 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( snddata->channels != 1 && snddata->channels != 2 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( snddata->bps != 8 && snddata->bps != 16 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
snddata->size = le32( wave->subchunk2size );
|
||||
snddata->samples = malloc( snddata->size );
|
||||
|
||||
if ( snddata->samples )
|
||||
{
|
||||
memcpy( (void*)snddata->samples, (void*)wave->data, snddata->size );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata )
|
||||
{
|
||||
int16_t* out_buffer;
|
||||
size_t in_samples;
|
||||
|
||||
if ( snddata->bps == 8 )
|
||||
{
|
||||
if ( snddata->channels == 1 )
|
||||
{
|
||||
/* 8 bps, mono. */
|
||||
in_samples = snddata->size;
|
||||
*out_samples = in_samples * 2;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint8_t* begin = (const uint8_t*)snddata->samples;
|
||||
const uint8_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
int sample = *begin++;
|
||||
sample = sample * 65792 / 256 - 32768;
|
||||
*samples++ = sample;
|
||||
*samples++ = sample;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 8 bps, stereo. */
|
||||
in_samples = snddata->size;
|
||||
*out_samples = in_samples;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint8_t* begin = (const uint8_t*)snddata->samples;
|
||||
const uint8_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
int sample = *begin++;
|
||||
sample = sample * 65792 / 256 - 32768;
|
||||
*samples++ = sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( snddata->channels == 1 )
|
||||
{
|
||||
/* 16 bps, mono. */
|
||||
in_samples = snddata->size / 2;
|
||||
*out_samples = in_samples * 2;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint16_t* begin = (const uint16_t*)snddata->samples;
|
||||
const uint16_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
int16_t sample = le16( *begin++ );
|
||||
*samples++ = sample;
|
||||
*samples++ = sample;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 16 bps, stereo. */
|
||||
in_samples = snddata->size / 2;
|
||||
*out_samples = in_samples;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint16_t* begin = (const uint16_t*)snddata->samples;
|
||||
const uint16_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
*samples++ = le16( *begin++ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( snddata->freq != RL_SAMPLE_RATE )
|
||||
{
|
||||
rl_resampler_t* resampler = rl_resampler_create( snddata->freq );
|
||||
|
||||
if ( !resampler )
|
||||
{
|
||||
free( out_buffer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t new_samples = rl_resampler_out_samples( resampler, *out_samples );
|
||||
int16_t* new_buffer = (int16_t*)malloc( new_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !new_buffer )
|
||||
{
|
||||
rl_resampler_destroy( resampler );
|
||||
free( out_buffer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( rl_resampler_resample( resampler, out_buffer, *out_samples, new_buffer, new_samples ) != new_samples )
|
||||
{
|
||||
free( new_buffer );
|
||||
rl_resampler_destroy( resampler );
|
||||
free( out_buffer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free( out_buffer );
|
||||
out_buffer = new_buffer;
|
||||
*out_samples = new_samples;
|
||||
}
|
||||
|
||||
return out_buffer;
|
||||
}
|
||||
#include <rl_snddata.h>
|
||||
#include <rl_resample.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rl_endian.inl>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* header */
|
||||
char chunkid[ 4 ];
|
||||
uint32_t chunksize;
|
||||
char format[ 4 ];
|
||||
/* fmt */
|
||||
char subchunk1id[ 4 ];
|
||||
uint32_t subchunk1size;
|
||||
uint16_t audioformat;
|
||||
uint16_t numchannels;
|
||||
uint32_t samplerate;
|
||||
uint32_t byterate;
|
||||
uint16_t blockalign;
|
||||
uint16_t bitspersample;
|
||||
/* data */
|
||||
char subchunk2id[ 4 ];
|
||||
uint32_t subchunk2size;
|
||||
uint8_t data[ 0 ];
|
||||
|
||||
}
|
||||
wave_t;
|
||||
|
||||
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size )
|
||||
{
|
||||
const wave_t* wave = (const wave_t*)data;
|
||||
|
||||
if ( wave->chunkid[ 0 ] != 'R' || wave->chunkid[ 1 ] != 'I' || wave->chunkid[ 2 ] != 'F' || wave->chunkid[ 3 ] != 'F' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( wave->format[ 0 ] != 'W' || wave->format[ 1 ] != 'A' || wave->format[ 2 ] != 'V' || wave->format[ 3 ] != 'E' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( wave->subchunk1id[ 0 ] != 'f' || wave->subchunk1id[ 1 ] != 'm' || wave->subchunk1id[ 2 ] != 't' || wave->subchunk1id[ 3 ] != ' ' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( wave->subchunk2id[ 0 ] != 'd' || wave->subchunk2id[ 1 ] != 'a' || wave->subchunk2id[ 2 ] != 't' || wave->subchunk2id[ 3 ] != 'a' )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
snddata->bps = le16( wave->bitspersample );
|
||||
snddata->channels = le16( wave->numchannels );
|
||||
snddata->freq = le32( wave->samplerate );
|
||||
|
||||
if ( le16( wave->audioformat ) != 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( snddata->channels != 1 && snddata->channels != 2 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( snddata->bps != 8 && snddata->bps != 16 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
snddata->size = le32( wave->subchunk2size );
|
||||
snddata->samples = malloc( snddata->size );
|
||||
|
||||
if ( snddata->samples )
|
||||
{
|
||||
memcpy( (void*)snddata->samples, (void*)wave->data, snddata->size );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata )
|
||||
{
|
||||
int16_t* out_buffer;
|
||||
size_t in_samples;
|
||||
|
||||
if ( snddata->bps == 8 )
|
||||
{
|
||||
if ( snddata->channels == 1 )
|
||||
{
|
||||
/* 8 bps, mono. */
|
||||
in_samples = snddata->size;
|
||||
*out_samples = in_samples * 2;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint8_t* begin = (const uint8_t*)snddata->samples;
|
||||
const uint8_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
int sample = *begin++;
|
||||
sample = sample * 65792 / 256 - 32768;
|
||||
*samples++ = sample;
|
||||
*samples++ = sample;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 8 bps, stereo. */
|
||||
in_samples = snddata->size;
|
||||
*out_samples = in_samples;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint8_t* begin = (const uint8_t*)snddata->samples;
|
||||
const uint8_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
int sample = *begin++;
|
||||
sample = sample * 65792 / 256 - 32768;
|
||||
*samples++ = sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( snddata->channels == 1 )
|
||||
{
|
||||
/* 16 bps, mono. */
|
||||
in_samples = snddata->size / 2;
|
||||
*out_samples = in_samples * 2;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint16_t* begin = (const uint16_t*)snddata->samples;
|
||||
const uint16_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
int16_t sample = le16( *begin++ );
|
||||
*samples++ = sample;
|
||||
*samples++ = sample;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 16 bps, stereo. */
|
||||
in_samples = snddata->size / 2;
|
||||
*out_samples = in_samples;
|
||||
out_buffer = (int16_t*)malloc( *out_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !out_buffer )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int16_t* samples = out_buffer;
|
||||
const uint16_t* begin = (const uint16_t*)snddata->samples;
|
||||
const uint16_t* end = begin + in_samples;
|
||||
|
||||
while ( begin < end )
|
||||
{
|
||||
*samples++ = le16( *begin++ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( snddata->freq != RL_SAMPLE_RATE )
|
||||
{
|
||||
rl_resampler_t* resampler = rl_resampler_create( snddata->freq );
|
||||
|
||||
if ( !resampler )
|
||||
{
|
||||
free( out_buffer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t new_samples = rl_resampler_out_samples( resampler, *out_samples );
|
||||
int16_t* new_buffer = (int16_t*)malloc( new_samples * sizeof( int16_t ) );
|
||||
|
||||
if ( !new_buffer )
|
||||
{
|
||||
rl_resampler_destroy( resampler );
|
||||
free( out_buffer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( rl_resampler_resample( resampler, out_buffer, *out_samples, new_buffer, new_samples ) != new_samples )
|
||||
{
|
||||
free( new_buffer );
|
||||
rl_resampler_destroy( resampler );
|
||||
free( out_buffer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free( out_buffer );
|
||||
out_buffer = new_buffer;
|
||||
*out_samples = new_samples;
|
||||
}
|
||||
|
||||
return out_buffer;
|
||||
}
|
||||
|
@ -1,27 +1,28 @@
|
||||
#ifndef RL_SNDDATA_H
|
||||
#define RL_SNDDATA_H
|
||||
|
||||
#include <rl_userdata.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rl_userdata_t ud;
|
||||
|
||||
int bps; /* bits per sample */
|
||||
int channels; /* number of channels */
|
||||
int freq; /* frequency */
|
||||
|
||||
size_t size;
|
||||
const void* samples;
|
||||
}
|
||||
rl_snddata_t;
|
||||
|
||||
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size );
|
||||
#define rl_snddata_destroy( snddata ) do { free( (void*)( snddata )->samples ); } while ( 0 )
|
||||
|
||||
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata );
|
||||
|
||||
#endif /* RL_SNDDATA_H */
|
||||
#ifndef RL_SNDDATA_H
|
||||
#define RL_SNDDATA_H
|
||||
|
||||
#include <rl_userdata.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rl_userdata_t ud;
|
||||
|
||||
int bps; /* bits per sample */
|
||||
int channels; /* number of channels */
|
||||
int freq; /* frequency */
|
||||
|
||||
size_t size;
|
||||
const void* samples;
|
||||
}
|
||||
rl_snddata_t;
|
||||
|
||||
int rl_snddata_create( rl_snddata_t* snddata, const void* data, size_t size );
|
||||
#define rl_snddata_destroy( snddata ) do { free( (void*)( snddata )->samples ); } while ( 0 )
|
||||
|
||||
const int16_t* rl_snddata_encode( size_t* out_samples, const rl_snddata_t* snddata );
|
||||
|
||||
#endif /* RL_SNDDATA_H */
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Reasons passed to the stop callback. */
|
||||
#define RL_SOUND_FINISHED 0
|
||||
|
304
src/rl_xml.c
304
src/rl_xml.c
@ -1,152 +1,152 @@
|
||||
#include <rl_xml.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static inline void skip_to_tag( const char** xml )
|
||||
{
|
||||
const char* aux = *xml;
|
||||
|
||||
while ( *aux != '<' && *aux )
|
||||
{
|
||||
aux++;
|
||||
}
|
||||
|
||||
*xml = aux;
|
||||
}
|
||||
|
||||
static inline void skip_name( const char** xml )
|
||||
{
|
||||
const char* aux = *xml;
|
||||
|
||||
while ( !isspace( *aux ) && *aux != '>' && *aux != '=' && *aux )
|
||||
{
|
||||
aux++;
|
||||
}
|
||||
|
||||
*xml = aux;
|
||||
}
|
||||
|
||||
static inline void skip_spaces( const char** xml )
|
||||
{
|
||||
const char* aux = *xml;
|
||||
|
||||
while ( isspace( *aux ) )
|
||||
{
|
||||
aux++;
|
||||
}
|
||||
|
||||
*xml = aux;
|
||||
}
|
||||
|
||||
#define CHECK( stmt ) do { int res = stmt; if ( res ) return res; } while ( 0 )
|
||||
|
||||
static int parse( const char* xml, const char* end, rl_xmlhandlers_t* handlers )
|
||||
{
|
||||
CHECK( handlers->start_document( handlers ) );
|
||||
|
||||
do
|
||||
{
|
||||
const char* text = xml;
|
||||
skip_to_tag( &xml );
|
||||
|
||||
if ( xml != text )
|
||||
{
|
||||
CHECK( handlers->characters( handlers, text, xml - text ) );
|
||||
}
|
||||
|
||||
if ( *xml != '<' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( xml[ 1 ] == '/' )
|
||||
{
|
||||
const char* name = xml += 2;
|
||||
skip_name( &xml );
|
||||
CHECK( handlers->end_element( handlers, name, xml - name ) );
|
||||
skip_spaces( &xml );
|
||||
|
||||
if ( *xml != '>' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml++;
|
||||
}
|
||||
else if ( xml[ 1 ] == '?' )
|
||||
{
|
||||
xml = strstr( xml + 2, "?>" );
|
||||
|
||||
if ( !xml )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* name = ++xml;
|
||||
skip_name( &xml );
|
||||
size_t name_length = xml - name;
|
||||
CHECK( handlers->start_element( handlers, name, name_length ) );
|
||||
|
||||
skip_spaces( &xml );
|
||||
|
||||
while ( *xml != '>' && *xml != '/' )
|
||||
{
|
||||
const char* key = xml;
|
||||
skip_name( &xml );
|
||||
size_t key_length = xml - key;
|
||||
|
||||
skip_spaces( &xml );
|
||||
|
||||
if ( *xml != '=' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml++;
|
||||
skip_spaces( &xml );
|
||||
char quote = *xml++;
|
||||
const char* value = xml;
|
||||
|
||||
xml = strchr( xml, quote );
|
||||
|
||||
if ( !xml )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
CHECK( handlers->attribute( handlers, key, key_length, value, xml - value ) );
|
||||
|
||||
xml++;
|
||||
skip_spaces( &xml );
|
||||
}
|
||||
|
||||
if ( *xml == '/' )
|
||||
{
|
||||
CHECK( handlers->end_element( handlers, name, name_length ) );
|
||||
xml++;
|
||||
skip_spaces( &xml );
|
||||
|
||||
if ( *xml != '>' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
xml++;
|
||||
}
|
||||
}
|
||||
while ( *xml );
|
||||
|
||||
out:
|
||||
return handlers->end_document( handlers );
|
||||
}
|
||||
|
||||
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers )
|
||||
{
|
||||
return parse( xml, xml + length, handlers );
|
||||
}
|
||||
#include <rl_xml.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static inline void skip_to_tag( const char** xml )
|
||||
{
|
||||
const char* aux = *xml;
|
||||
|
||||
while ( *aux != '<' && *aux )
|
||||
{
|
||||
aux++;
|
||||
}
|
||||
|
||||
*xml = aux;
|
||||
}
|
||||
|
||||
static inline void skip_name( const char** xml )
|
||||
{
|
||||
const char* aux = *xml;
|
||||
|
||||
while ( !isspace( *aux ) && *aux != '>' && *aux != '=' && *aux )
|
||||
{
|
||||
aux++;
|
||||
}
|
||||
|
||||
*xml = aux;
|
||||
}
|
||||
|
||||
static inline void skip_spaces( const char** xml )
|
||||
{
|
||||
const char* aux = *xml;
|
||||
|
||||
while ( isspace( *aux ) )
|
||||
{
|
||||
aux++;
|
||||
}
|
||||
|
||||
*xml = aux;
|
||||
}
|
||||
|
||||
#define CHECK( stmt ) do { int res = stmt; if ( res ) return res; } while ( 0 )
|
||||
|
||||
static int parse( const char* xml, const char* end, rl_xmlhandlers_t* handlers )
|
||||
{
|
||||
CHECK( handlers->start_document( handlers ) );
|
||||
|
||||
do
|
||||
{
|
||||
const char* text = xml;
|
||||
skip_to_tag( &xml );
|
||||
|
||||
if ( xml != text )
|
||||
{
|
||||
CHECK( handlers->characters( handlers, text, xml - text ) );
|
||||
}
|
||||
|
||||
if ( *xml != '<' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( xml[ 1 ] == '/' )
|
||||
{
|
||||
const char* name = xml += 2;
|
||||
skip_name( &xml );
|
||||
CHECK( handlers->end_element( handlers, name, xml - name ) );
|
||||
skip_spaces( &xml );
|
||||
|
||||
if ( *xml != '>' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml++;
|
||||
}
|
||||
else if ( xml[ 1 ] == '?' )
|
||||
{
|
||||
xml = strstr( xml + 2, "?>" );
|
||||
|
||||
if ( !xml )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* name = ++xml;
|
||||
skip_name( &xml );
|
||||
size_t name_length = xml - name;
|
||||
CHECK( handlers->start_element( handlers, name, name_length ) );
|
||||
|
||||
skip_spaces( &xml );
|
||||
|
||||
while ( *xml != '>' && *xml != '/' )
|
||||
{
|
||||
const char* key = xml;
|
||||
skip_name( &xml );
|
||||
size_t key_length = xml - key;
|
||||
|
||||
skip_spaces( &xml );
|
||||
|
||||
if ( *xml != '=' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
xml++;
|
||||
skip_spaces( &xml );
|
||||
char quote = *xml++;
|
||||
const char* value = xml;
|
||||
|
||||
xml = strchr( xml, quote );
|
||||
|
||||
if ( !xml )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
CHECK( handlers->attribute( handlers, key, key_length, value, xml - value ) );
|
||||
|
||||
xml++;
|
||||
skip_spaces( &xml );
|
||||
}
|
||||
|
||||
if ( *xml == '/' )
|
||||
{
|
||||
CHECK( handlers->end_element( handlers, name, name_length ) );
|
||||
xml++;
|
||||
skip_spaces( &xml );
|
||||
|
||||
if ( *xml != '>' )
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
xml++;
|
||||
}
|
||||
}
|
||||
while ( *xml );
|
||||
|
||||
out:
|
||||
return handlers->end_document( handlers );
|
||||
}
|
||||
|
||||
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers )
|
||||
{
|
||||
return parse( xml, xml + length, handlers );
|
||||
}
|
||||
|
48
src/rl_xml.h
48
src/rl_xml.h
@ -1,24 +1,24 @@
|
||||
#ifndef RL_XML_H
|
||||
#define RL_XML_H
|
||||
|
||||
#include <rl_userdata.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct rl_xmlhandlers_t rl_xmlhandlers_t;
|
||||
|
||||
struct rl_xmlhandlers_t
|
||||
{
|
||||
rl_userdata_t ud;
|
||||
|
||||
int ( *start_document )( rl_xmlhandlers_t* handlers );
|
||||
int ( *end_document )( rl_xmlhandlers_t* handlers );
|
||||
int ( *start_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
|
||||
int ( *end_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
|
||||
int ( *attribute )( rl_xmlhandlers_t* handlers, const char* key, size_t key_length, const char* value, size_t value_length );
|
||||
int ( *characters )( rl_xmlhandlers_t* handlers, const char* text, size_t length );
|
||||
};
|
||||
|
||||
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers );
|
||||
|
||||
#endif /* RL_XML_H */
|
||||
#ifndef RL_XML_H
|
||||
#define RL_XML_H
|
||||
|
||||
#include <rl_userdata.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct rl_xmlhandlers_t rl_xmlhandlers_t;
|
||||
|
||||
struct rl_xmlhandlers_t
|
||||
{
|
||||
rl_userdata_t ud;
|
||||
|
||||
int ( *start_document )( rl_xmlhandlers_t* handlers );
|
||||
int ( *end_document )( rl_xmlhandlers_t* handlers );
|
||||
int ( *start_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
|
||||
int ( *end_element )( rl_xmlhandlers_t* handlers, const char* name, size_t length );
|
||||
int ( *attribute )( rl_xmlhandlers_t* handlers, const char* key, size_t key_length, const char* value, size_t value_length );
|
||||
int ( *characters )( rl_xmlhandlers_t* handlers, const char* text, size_t length );
|
||||
};
|
||||
|
||||
int rl_xml_parse( const char* xml, size_t length, rl_xmlhandlers_t* handlers );
|
||||
|
||||
#endif /* RL_XML_H */
|
||||
|
Loading…
Reference in New Issue
Block a user