Built SDL2_image and _mixer static
This commit is contained in:
389
libsdl2_mixer/external/opusfile-0.10/examples/opusfile_example.c
vendored
Normal file
389
libsdl2_mixer/external/opusfile-0.10/examples/opusfile_example.c
vendored
Normal file
@ -0,0 +1,389 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 *
|
||||
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/*For fileno()*/
|
||||
#if !defined(_POSIX_SOURCE)
|
||||
# define _POSIX_SOURCE 1
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <opusfile.h>
|
||||
#if defined(_WIN32)
|
||||
# include "win32utf8.h"
|
||||
# undef fileno
|
||||
# define fileno _fileno
|
||||
#endif
|
||||
|
||||
static void print_duration(FILE *_fp,ogg_int64_t _nsamples,int _frac){
|
||||
ogg_int64_t seconds;
|
||||
ogg_int64_t minutes;
|
||||
ogg_int64_t hours;
|
||||
ogg_int64_t days;
|
||||
ogg_int64_t weeks;
|
||||
_nsamples+=_frac?24:24000;
|
||||
seconds=_nsamples/48000;
|
||||
_nsamples-=seconds*48000;
|
||||
minutes=seconds/60;
|
||||
seconds-=minutes*60;
|
||||
hours=minutes/60;
|
||||
minutes-=hours*60;
|
||||
days=hours/24;
|
||||
hours-=days*24;
|
||||
weeks=days/7;
|
||||
days-=weeks*7;
|
||||
if(weeks)fprintf(_fp,"%liw",(long)weeks);
|
||||
if(weeks||days)fprintf(_fp,"%id",(int)days);
|
||||
if(weeks||days||hours){
|
||||
if(weeks||days)fprintf(_fp,"%02ih",(int)hours);
|
||||
else fprintf(_fp,"%ih",(int)hours);
|
||||
}
|
||||
if(weeks||days||hours||minutes){
|
||||
if(weeks||days||hours)fprintf(_fp,"%02im",(int)minutes);
|
||||
else fprintf(_fp,"%im",(int)minutes);
|
||||
fprintf(_fp,"%02i",(int)seconds);
|
||||
}
|
||||
else fprintf(_fp,"%i",(int)seconds);
|
||||
if(_frac)fprintf(_fp,".%03i",(int)(_nsamples/48));
|
||||
fprintf(_fp,"s");
|
||||
}
|
||||
|
||||
static void print_size(FILE *_fp,opus_int64 _nbytes,int _metric,
|
||||
const char *_spacer){
|
||||
static const char SUFFIXES[7]={' ','k','M','G','T','P','E'};
|
||||
opus_int64 val;
|
||||
opus_int64 den;
|
||||
opus_int64 round;
|
||||
int base;
|
||||
int shift;
|
||||
base=_metric?1000:1024;
|
||||
round=0;
|
||||
den=1;
|
||||
for(shift=0;shift<6;shift++){
|
||||
if(_nbytes<den*base-round)break;
|
||||
den*=base;
|
||||
round=den>>1;
|
||||
}
|
||||
val=(_nbytes+round)/den;
|
||||
if(den>1&&val<10){
|
||||
if(den>=1000000000)val=(_nbytes+(round/100))/(den/100);
|
||||
else val=(_nbytes*100+round)/den;
|
||||
fprintf(_fp,"%li.%02i%s%c",(long)(val/100),(int)(val%100),
|
||||
_spacer,SUFFIXES[shift]);
|
||||
}
|
||||
else if(den>1&&val<100){
|
||||
if(den>=1000000000)val=(_nbytes+(round/10))/(den/10);
|
||||
else val=(_nbytes*10+round)/den;
|
||||
fprintf(_fp,"%li.%i%s%c",(long)(val/10),(int)(val%10),
|
||||
_spacer,SUFFIXES[shift]);
|
||||
}
|
||||
else fprintf(_fp,"%li%s%c",(long)val,_spacer,SUFFIXES[shift]);
|
||||
}
|
||||
|
||||
static void put_le32(unsigned char *_dst,opus_uint32 _x){
|
||||
_dst[0]=(unsigned char)(_x&0xFF);
|
||||
_dst[1]=(unsigned char)(_x>>8&0xFF);
|
||||
_dst[2]=(unsigned char)(_x>>16&0xFF);
|
||||
_dst[3]=(unsigned char)(_x>>24&0xFF);
|
||||
}
|
||||
|
||||
/*Make a header for a 48 kHz, stereo, signed, 16-bit little-endian PCM WAV.*/
|
||||
static void make_wav_header(unsigned char _dst[44],ogg_int64_t _duration){
|
||||
/*The chunk sizes are set to 0x7FFFFFFF by default.
|
||||
Many, though not all, programs will interpret this to mean the duration is
|
||||
"undefined", and continue to read from the file so long as there is actual
|
||||
data.*/
|
||||
static const unsigned char WAV_HEADER_TEMPLATE[44]={
|
||||
'R','I','F','F',0xFF,0xFF,0xFF,0x7F,
|
||||
'W','A','V','E','f','m','t',' ',
|
||||
0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,
|
||||
0x80,0xBB,0x00,0x00,0x00,0xEE,0x02,0x00,
|
||||
0x04,0x00,0x10,0x00,'d','a','t','a',
|
||||
0xFF,0xFF,0xFF,0x7F
|
||||
};
|
||||
memcpy(_dst,WAV_HEADER_TEMPLATE,sizeof(WAV_HEADER_TEMPLATE));
|
||||
if(_duration>0){
|
||||
if(_duration>0x1FFFFFF6){
|
||||
fprintf(stderr,"WARNING: WAV output would be larger than 2 GB.\n");
|
||||
fprintf(stderr,
|
||||
"Writing non-standard WAV header with invalid chunk sizes.\n");
|
||||
}
|
||||
else{
|
||||
opus_uint32 audio_size;
|
||||
audio_size=(opus_uint32)(_duration*4);
|
||||
put_le32(_dst+4,audio_size+36);
|
||||
put_le32(_dst+40,audio_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int _argc,const char **_argv){
|
||||
OggOpusFile *of;
|
||||
ogg_int64_t duration;
|
||||
unsigned char wav_header[44];
|
||||
int ret;
|
||||
int is_ssl;
|
||||
int output_seekable;
|
||||
#if defined(_WIN32)
|
||||
win32_utf8_setup(&_argc,&_argv);
|
||||
#endif
|
||||
if(_argc!=2){
|
||||
fprintf(stderr,"Usage: %s <file.opus>\n",_argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
is_ssl=0;
|
||||
if(strcmp(_argv[1],"-")==0){
|
||||
OpusFileCallbacks cb={NULL,NULL,NULL,NULL};
|
||||
of=op_open_callbacks(op_fdopen(&cb,fileno(stdin),"rb"),&cb,NULL,0,&ret);
|
||||
}
|
||||
else{
|
||||
OpusServerInfo info;
|
||||
/*Try to treat the argument as a URL.*/
|
||||
of=op_open_url(_argv[1],&ret,OP_GET_SERVER_INFO(&info),NULL);
|
||||
#if 0
|
||||
if(of==NULL){
|
||||
OpusFileCallbacks cb={NULL,NULL,NULL,NULL};
|
||||
void *fp;
|
||||
/*For debugging: force a file to not be seekable.*/
|
||||
fp=op_fopen(&cb,_argv[1],"rb");
|
||||
cb.seek=NULL;
|
||||
cb.tell=NULL;
|
||||
of=op_open_callbacks(fp,&cb,NULL,0,NULL);
|
||||
}
|
||||
#else
|
||||
if(of==NULL)of=op_open_file(_argv[1],&ret);
|
||||
#endif
|
||||
else{
|
||||
if(info.name!=NULL){
|
||||
fprintf(stderr,"Station name: %s\n",info.name);
|
||||
}
|
||||
if(info.description!=NULL){
|
||||
fprintf(stderr,"Station description: %s\n",info.description);
|
||||
}
|
||||
if(info.genre!=NULL){
|
||||
fprintf(stderr,"Station genre: %s\n",info.genre);
|
||||
}
|
||||
if(info.url!=NULL){
|
||||
fprintf(stderr,"Station homepage: %s\n",info.url);
|
||||
}
|
||||
if(info.bitrate_kbps>=0){
|
||||
fprintf(stderr,"Station bitrate: %u kbps\n",
|
||||
(unsigned)info.bitrate_kbps);
|
||||
}
|
||||
if(info.is_public>=0){
|
||||
fprintf(stderr,"%s\n",
|
||||
info.is_public?"Station is public.":"Station is private.");
|
||||
}
|
||||
if(info.server!=NULL){
|
||||
fprintf(stderr,"Server software: %s\n",info.server);
|
||||
}
|
||||
if(info.content_type!=NULL){
|
||||
fprintf(stderr,"Content-Type: %s\n",info.content_type);
|
||||
}
|
||||
is_ssl=info.is_ssl;
|
||||
opus_server_info_clear(&info);
|
||||
}
|
||||
}
|
||||
if(of==NULL){
|
||||
fprintf(stderr,"Failed to open file '%s': %i\n",_argv[1],ret);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
duration=0;
|
||||
output_seekable=fseek(stdout,0,SEEK_CUR)!=-1;
|
||||
if(op_seekable(of)){
|
||||
opus_int64 size;
|
||||
fprintf(stderr,"Total number of links: %i\n",op_link_count(of));
|
||||
duration=op_pcm_total(of,-1);
|
||||
fprintf(stderr,"Total duration: ");
|
||||
print_duration(stderr,duration,3);
|
||||
fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
|
||||
size=op_raw_total(of,-1);
|
||||
fprintf(stderr,"Total size: ");
|
||||
print_size(stderr,size,0,"");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
else if(!output_seekable){
|
||||
fprintf(stderr,"WARNING: Neither input nor output are seekable.\n");
|
||||
fprintf(stderr,
|
||||
"Writing non-standard WAV header with invalid chunk sizes.\n");
|
||||
}
|
||||
make_wav_header(wav_header,duration);
|
||||
if(!fwrite(wav_header,sizeof(wav_header),1,stdout)){
|
||||
fprintf(stderr,"Error writing WAV header: %s\n",strerror(errno));
|
||||
ret=EXIT_FAILURE;
|
||||
}
|
||||
else{
|
||||
ogg_int64_t pcm_offset;
|
||||
ogg_int64_t pcm_print_offset;
|
||||
ogg_int64_t nsamples;
|
||||
opus_int32 bitrate;
|
||||
int prev_li;
|
||||
prev_li=-1;
|
||||
nsamples=0;
|
||||
pcm_offset=op_pcm_tell(of);
|
||||
if(pcm_offset!=0){
|
||||
fprintf(stderr,"Non-zero starting PCM offset: %li\n",(long)pcm_offset);
|
||||
}
|
||||
pcm_print_offset=pcm_offset-48000;
|
||||
bitrate=0;
|
||||
for(;;){
|
||||
ogg_int64_t next_pcm_offset;
|
||||
opus_int16 pcm[120*48*2];
|
||||
unsigned char out[120*48*2*2];
|
||||
int li;
|
||||
int si;
|
||||
/*Although we would generally prefer to use the float interface, WAV
|
||||
files with signed, 16-bit little-endian samples are far more
|
||||
universally supported, so that's what we output.*/
|
||||
ret=op_read_stereo(of,pcm,sizeof(pcm)/sizeof(*pcm));
|
||||
if(ret==OP_HOLE){
|
||||
fprintf(stderr,"\nHole detected! Corrupt file segment?\n");
|
||||
continue;
|
||||
}
|
||||
else if(ret<0){
|
||||
fprintf(stderr,"\nError decoding '%s': %i\n",_argv[1],ret);
|
||||
if(is_ssl)fprintf(stderr,"Possible truncation attack?\n");
|
||||
ret=EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
li=op_current_link(of);
|
||||
if(li!=prev_li){
|
||||
const OpusHead *head;
|
||||
const OpusTags *tags;
|
||||
int binary_suffix_len;
|
||||
int ci;
|
||||
/*We found a new link.
|
||||
Print out some information.*/
|
||||
fprintf(stderr,"Decoding link %i: \n",li);
|
||||
head=op_head(of,li);
|
||||
fprintf(stderr," Channels: %i\n",head->channel_count);
|
||||
if(op_seekable(of)){
|
||||
ogg_int64_t duration;
|
||||
opus_int64 size;
|
||||
duration=op_pcm_total(of,li);
|
||||
fprintf(stderr," Duration: ");
|
||||
print_duration(stderr,duration,3);
|
||||
fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
|
||||
size=op_raw_total(of,li);
|
||||
fprintf(stderr," Size: ");
|
||||
print_size(stderr,size,0,"");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
if(head->input_sample_rate){
|
||||
fprintf(stderr," Original sampling rate: %lu Hz\n",
|
||||
(unsigned long)head->input_sample_rate);
|
||||
}
|
||||
tags=op_tags(of,li);
|
||||
fprintf(stderr," Encoded by: %s\n",tags->vendor);
|
||||
for(ci=0;ci<tags->comments;ci++){
|
||||
const char *comment;
|
||||
comment=tags->user_comments[ci];
|
||||
if(opus_tagncompare("METADATA_BLOCK_PICTURE",22,comment)==0){
|
||||
OpusPictureTag pic;
|
||||
int err;
|
||||
err=opus_picture_tag_parse(&pic,comment);
|
||||
fprintf(stderr," %.23s",comment);
|
||||
if(err>=0){
|
||||
fprintf(stderr,"%u|%s|%s|%ux%ux%u",pic.type,pic.mime_type,
|
||||
pic.description,pic.width,pic.height,pic.depth);
|
||||
if(pic.colors!=0)fprintf(stderr,"/%u",pic.colors);
|
||||
if(pic.format==OP_PIC_FORMAT_URL){
|
||||
fprintf(stderr,"|%s\n",pic.data);
|
||||
}
|
||||
else{
|
||||
fprintf(stderr,"|<%u bytes of image data>\n",pic.data_length);
|
||||
}
|
||||
opus_picture_tag_clear(&pic);
|
||||
}
|
||||
else fprintf(stderr,"<error parsing picture tag>\n");
|
||||
}
|
||||
else fprintf(stderr," %s\n",tags->user_comments[ci]);
|
||||
}
|
||||
if(opus_tags_get_binary_suffix(tags,&binary_suffix_len)!=NULL){
|
||||
fprintf(stderr,"<%u bytes of unknown binary metadata>\n",
|
||||
binary_suffix_len);
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
if(!op_seekable(of)){
|
||||
pcm_offset=op_pcm_tell(of)-ret;
|
||||
if(pcm_offset!=0){
|
||||
fprintf(stderr,"Non-zero starting PCM offset in link %i: %li\n",
|
||||
li,(long)pcm_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(li!=prev_li||pcm_offset>=pcm_print_offset+48000){
|
||||
opus_int32 next_bitrate;
|
||||
opus_int64 raw_offset;
|
||||
next_bitrate=op_bitrate_instant(of);
|
||||
if(next_bitrate>=0)bitrate=next_bitrate;
|
||||
raw_offset=op_raw_tell(of);
|
||||
fprintf(stderr,"\r ");
|
||||
print_size(stderr,raw_offset,0,"");
|
||||
fprintf(stderr," ");
|
||||
print_duration(stderr,pcm_offset,0);
|
||||
fprintf(stderr," (");
|
||||
print_size(stderr,bitrate,1," ");
|
||||
fprintf(stderr,"bps) \r");
|
||||
pcm_print_offset=pcm_offset;
|
||||
fflush(stderr);
|
||||
}
|
||||
next_pcm_offset=op_pcm_tell(of);
|
||||
if(pcm_offset+ret!=next_pcm_offset){
|
||||
fprintf(stderr,"\nPCM offset gap! %li+%i!=%li\n",
|
||||
(long)pcm_offset,ret,(long)next_pcm_offset);
|
||||
}
|
||||
pcm_offset=next_pcm_offset;
|
||||
if(ret<=0){
|
||||
ret=EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
/*Ensure the data is little-endian before writing it out.*/
|
||||
for(si=0;si<2*ret;si++){
|
||||
out[2*si+0]=(unsigned char)(pcm[si]&0xFF);
|
||||
out[2*si+1]=(unsigned char)(pcm[si]>>8&0xFF);
|
||||
}
|
||||
if(!fwrite(out,sizeof(*out)*4*ret,1,stdout)){
|
||||
fprintf(stderr,"\nError writing decoded audio data: %s\n",
|
||||
strerror(errno));
|
||||
ret=EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
nsamples+=ret;
|
||||
prev_li=li;
|
||||
}
|
||||
if(ret==EXIT_SUCCESS){
|
||||
fprintf(stderr,"\nDone: played ");
|
||||
print_duration(stderr,nsamples,3);
|
||||
fprintf(stderr," (%li samples @ 48 kHz).\n",(long)nsamples);
|
||||
}
|
||||
if(op_seekable(of)&&nsamples!=duration){
|
||||
fprintf(stderr,"\nWARNING: "
|
||||
"Number of output samples does not match declared file duration.\n");
|
||||
if(!output_seekable)fprintf(stderr,"Output WAV file will be corrupt.\n");
|
||||
}
|
||||
if(output_seekable&&nsamples!=duration){
|
||||
make_wav_header(wav_header,nsamples);
|
||||
if(fseek(stdout,0,SEEK_SET)||
|
||||
!fwrite(wav_header,sizeof(wav_header),1,stdout)){
|
||||
fprintf(stderr,"Error rewriting WAV header: %s\n",strerror(errno));
|
||||
ret=EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
op_free(of);
|
||||
return ret;
|
||||
}
|
464
libsdl2_mixer/external/opusfile-0.10/examples/seeking_example.c
vendored
Normal file
464
libsdl2_mixer/external/opusfile-0.10/examples/seeking_example.c
vendored
Normal file
@ -0,0 +1,464 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 *
|
||||
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/*For fileno()*/
|
||||
#if !defined(_POSIX_SOURCE)
|
||||
# define _POSIX_SOURCE 1
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <opusfile.h>
|
||||
#if defined(_WIN32)
|
||||
# include "win32utf8.h"
|
||||
# undef fileno
|
||||
# define fileno _fileno
|
||||
#endif
|
||||
|
||||
/*Use shorts, they're smaller.*/
|
||||
#if !defined(OP_FIXED_POINT)
|
||||
# define OP_FIXED_POINT (1)
|
||||
#endif
|
||||
|
||||
#if defined(OP_FIXED_POINT)
|
||||
|
||||
typedef opus_int16 op_sample;
|
||||
|
||||
# define op_read_native op_read
|
||||
|
||||
/*TODO: The convergence after 80 ms of preroll is far from exact.
|
||||
Our comparison is very rough.
|
||||
Need to find some way to do this better.*/
|
||||
# define MATCH_TOL (16384)
|
||||
|
||||
# define ABS(_x) ((_x)<0?-(_x):(_x))
|
||||
|
||||
# define MATCH(_a,_b) (ABS((_a)-(_b))<MATCH_TOL)
|
||||
|
||||
/*Don't have fixed-point downmixing code.*/
|
||||
# undef OP_WRITE_SEEK_SAMPLES
|
||||
|
||||
#else
|
||||
|
||||
typedef float op_sample;
|
||||
|
||||
# define op_read_native op_read_float
|
||||
|
||||
/*TODO: The convergence after 80 ms of preroll is far from exact.
|
||||
Our comparison is very rough.
|
||||
Need to find some way to do this better.*/
|
||||
# define MATCH_TOL (16384.0/32768)
|
||||
|
||||
# define FABS(_x) ((_x)<0?-(_x):(_x))
|
||||
|
||||
# define MATCH(_a,_b) (FABS((_a)-(_b))<MATCH_TOL)
|
||||
|
||||
# if defined(OP_WRITE_SEEK_SAMPLES)
|
||||
/*Matrices for downmixing from the supported channel counts to stereo.*/
|
||||
static const float DOWNMIX_MATRIX[8][8][2]={
|
||||
/*mono*/
|
||||
{
|
||||
{1.F,1.F}
|
||||
},
|
||||
/*stereo*/
|
||||
{
|
||||
{1.F,0.F},{0.F,1.F}
|
||||
},
|
||||
/*3.0*/
|
||||
{
|
||||
{0.5858F,0.F},{0.4142F,0.4142F},{0,0.5858F}
|
||||
},
|
||||
/*quadrophonic*/
|
||||
{
|
||||
{0.4226F,0.F},{0,0.4226F},{0.366F,0.2114F},{0.2114F,0.336F}
|
||||
},
|
||||
/*5.0*/
|
||||
{
|
||||
{0.651F,0.F},{0.46F,0.46F},{0,0.651F},{0.5636F,0.3254F},{0.3254F,0.5636F}
|
||||
},
|
||||
/*5.1*/
|
||||
{
|
||||
{0.529F,0.F},{0.3741F,0.3741F},{0.F,0.529F},{0.4582F,0.2645F},
|
||||
{0.2645F,0.4582F},{0.3741F,0.3741F}
|
||||
},
|
||||
/*6.1*/
|
||||
{
|
||||
{0.4553F,0.F},{0.322F,0.322F},{0.F,0.4553F},{0.3943F,0.2277F},
|
||||
{0.2277F,0.3943F},{0.2788F,0.2788F},{0.322F,0.322F}
|
||||
},
|
||||
/*7.1*/
|
||||
{
|
||||
{0.3886F,0.F},{0.2748F,0.2748F},{0.F,0.3886F},{0.3366F,0.1943F},
|
||||
{0.1943F,0.3366F},{0.3366F,0.1943F},{0.1943F,0.3366F},{0.2748F,0.2748F}
|
||||
}
|
||||
};
|
||||
|
||||
static void write_samples(float *_samples,int _nsamples,int _nchannels){
|
||||
float stereo_pcm[120*48*2];
|
||||
int i;
|
||||
for(i=0;i<_nsamples;i++){
|
||||
float l;
|
||||
float r;
|
||||
int ci;
|
||||
l=r=0.F;
|
||||
for(ci=0;ci<_nchannels;ci++){
|
||||
l+=DOWNMIX_MATRIX[_nchannels-1][ci][0]*_samples[i*_nchannels+ci];
|
||||
r+=DOWNMIX_MATRIX[_nchannels-1][ci][1]*_samples[i*_nchannels+ci];
|
||||
}
|
||||
stereo_pcm[2*i+0]=l;
|
||||
stereo_pcm[2*i+1]=r;
|
||||
}
|
||||
fwrite(stereo_pcm,sizeof(*stereo_pcm)*2,_nsamples,stdout);
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
static long nfailures;
|
||||
|
||||
static void verify_seek(OggOpusFile *_of,opus_int64 _byte_offset,
|
||||
ogg_int64_t _pcm_offset,ogg_int64_t _pcm_length,op_sample *_bigassbuffer){
|
||||
opus_int64 byte_offset;
|
||||
ogg_int64_t pcm_offset;
|
||||
ogg_int64_t duration;
|
||||
op_sample buffer[120*48*8];
|
||||
int nchannels;
|
||||
int nsamples;
|
||||
int li;
|
||||
int lj;
|
||||
int i;
|
||||
byte_offset=op_raw_tell(_of);
|
||||
if(_byte_offset!=-1&&byte_offset<_byte_offset){
|
||||
fprintf(stderr,"\nRaw position out of tolerance: requested %li, "
|
||||
"got %li.\n",(long)_byte_offset,(long)byte_offset);
|
||||
nfailures++;
|
||||
}
|
||||
pcm_offset=op_pcm_tell(_of);
|
||||
if(_pcm_offset!=-1&&pcm_offset>_pcm_offset){
|
||||
fprintf(stderr,"\nPCM position out of tolerance: requested %li, "
|
||||
"got %li.\n",(long)_pcm_offset,(long)pcm_offset);
|
||||
nfailures++;
|
||||
}
|
||||
if(pcm_offset<0||pcm_offset>_pcm_length){
|
||||
fprintf(stderr,"\nPCM position out of bounds: got %li.\n",
|
||||
(long)pcm_offset);
|
||||
nfailures++;
|
||||
}
|
||||
nsamples=op_read_native(_of,buffer,sizeof(buffer)/sizeof(*buffer),&li);
|
||||
if(nsamples<0){
|
||||
fprintf(stderr,"\nFailed to read PCM data after seek: %i\n",nsamples);
|
||||
nfailures++;
|
||||
li=op_current_link(_of);
|
||||
}
|
||||
for(lj=0;lj<li;lj++){
|
||||
duration=op_pcm_total(_of,lj);
|
||||
if(0<=pcm_offset&&pcm_offset<duration){
|
||||
fprintf(stderr,"\nPCM data after seek came from the wrong link: "
|
||||
"expected %i, got %i.\n",lj,li);
|
||||
nfailures++;
|
||||
}
|
||||
pcm_offset-=duration;
|
||||
if(_bigassbuffer!=NULL)_bigassbuffer+=op_channel_count(_of,lj)*duration;
|
||||
}
|
||||
duration=op_pcm_total(_of,li);
|
||||
if(pcm_offset+nsamples>duration){
|
||||
fprintf(stderr,"\nPCM data after seek exceeded link duration: "
|
||||
"limit %li, got %li.\n",(long)duration,(long)(pcm_offset+nsamples));
|
||||
nfailures++;
|
||||
}
|
||||
nchannels=op_channel_count(_of,li);
|
||||
if(_bigassbuffer!=NULL){
|
||||
for(i=0;i<nsamples*nchannels;i++){
|
||||
if(!MATCH(buffer[i],_bigassbuffer[pcm_offset*nchannels+i])){
|
||||
ogg_int64_t j;
|
||||
fprintf(stderr,"\nData after seek doesn't match declared PCM "
|
||||
"position: mismatch %G\n",
|
||||
(double)buffer[i]-_bigassbuffer[pcm_offset*nchannels+i]);
|
||||
for(j=0;j<duration-nsamples;j++){
|
||||
for(i=0;i<nsamples*nchannels;i++){
|
||||
if(!MATCH(buffer[i],_bigassbuffer[j*nchannels+i]))break;
|
||||
}
|
||||
if(i==nsamples*nchannels){
|
||||
fprintf(stderr,"\nData after seek appears to match position %li.\n",
|
||||
(long)i);
|
||||
}
|
||||
}
|
||||
nfailures++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(OP_WRITE_SEEK_SAMPLES)
|
||||
write_samples(buffer,nsamples,nchannels);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define OP_MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
|
||||
|
||||
/*A simple wrapper that lets us count the number of underlying seek calls.*/
|
||||
|
||||
static op_seek_func real_seek;
|
||||
|
||||
static long nreal_seeks;
|
||||
|
||||
static int seek_stat_counter(void *_stream,opus_int64 _offset,int _whence){
|
||||
if(_whence==SEEK_SET)nreal_seeks++;
|
||||
/*SEEK_CUR with an offset of 0 is free, as is SEEK_END with an offset of 0
|
||||
(assuming we know the file size), so don't count them.*/
|
||||
else if(_offset!=0)nreal_seeks++;
|
||||
return (*real_seek)(_stream,_offset,_whence);
|
||||
}
|
||||
|
||||
#define NSEEK_TESTS (1000)
|
||||
|
||||
static void print_duration(FILE *_fp,ogg_int64_t _nsamples){
|
||||
ogg_int64_t seconds;
|
||||
ogg_int64_t minutes;
|
||||
ogg_int64_t hours;
|
||||
ogg_int64_t days;
|
||||
ogg_int64_t weeks;
|
||||
seconds=_nsamples/48000;
|
||||
_nsamples-=seconds*48000;
|
||||
minutes=seconds/60;
|
||||
seconds-=minutes*60;
|
||||
hours=minutes/60;
|
||||
minutes-=hours*60;
|
||||
days=hours/24;
|
||||
hours-=days*24;
|
||||
weeks=days/7;
|
||||
days-=weeks*7;
|
||||
if(weeks)fprintf(_fp,"%liw",(long)weeks);
|
||||
if(weeks||days)fprintf(_fp,"%id",(int)days);
|
||||
if(weeks||days||hours){
|
||||
if(weeks||days)fprintf(_fp,"%02ih",(int)hours);
|
||||
else fprintf(_fp,"%ih",(int)hours);
|
||||
}
|
||||
if(weeks||days||hours||minutes){
|
||||
if(weeks||days||hours)fprintf(_fp,"%02im",(int)minutes);
|
||||
else fprintf(_fp,"%im",(int)minutes);
|
||||
fprintf(_fp,"%02i",(int)seconds);
|
||||
}
|
||||
else fprintf(_fp,"%i",(int)seconds);
|
||||
fprintf(_fp,".%03is",(int)(_nsamples+24)/48);
|
||||
}
|
||||
|
||||
int main(int _argc,const char **_argv){
|
||||
OpusFileCallbacks cb;
|
||||
OggOpusFile *of;
|
||||
void *fp;
|
||||
#if defined(_WIN32)
|
||||
win32_utf8_setup(&_argc,&_argv);
|
||||
#endif
|
||||
if(_argc!=2){
|
||||
fprintf(stderr,"Usage: %s <file.opus>\n",_argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
memset(&cb,0,sizeof(cb));
|
||||
if(strcmp(_argv[1],"-")==0)fp=op_fdopen(&cb,fileno(stdin),"rb");
|
||||
else{
|
||||
/*Try to treat the argument as a URL.*/
|
||||
fp=op_url_stream_create(&cb,_argv[1],
|
||||
OP_SSL_SKIP_CERTIFICATE_CHECK(1),NULL);
|
||||
/*Fall back assuming it's a regular file name.*/
|
||||
if(fp==NULL)fp=op_fopen(&cb,_argv[1],"rb");
|
||||
}
|
||||
if(cb.seek!=NULL){
|
||||
real_seek=cb.seek;
|
||||
cb.seek=seek_stat_counter;
|
||||
}
|
||||
of=op_open_callbacks(fp,&cb,NULL,0,NULL);
|
||||
if(of==NULL){
|
||||
fprintf(stderr,"Failed to open file '%s'.\n",_argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(op_seekable(of)){
|
||||
op_sample *bigassbuffer;
|
||||
ogg_int64_t size;
|
||||
ogg_int64_t pcm_offset;
|
||||
ogg_int64_t pcm_length;
|
||||
ogg_int64_t nsamples;
|
||||
long max_seeks;
|
||||
int nlinks;
|
||||
int ret;
|
||||
int li;
|
||||
int i;
|
||||
/*Because we want to do sample-level verification that the seek does what
|
||||
it claimed, decode the entire file into memory.*/
|
||||
nlinks=op_link_count(of);
|
||||
fprintf(stderr,"Opened file containing %i links with %li seeks "
|
||||
"(%0.3f per link).\n",nlinks,nreal_seeks,nreal_seeks/(double)nlinks);
|
||||
/*Reset the seek counter.*/
|
||||
nreal_seeks=0;
|
||||
nsamples=0;
|
||||
for(li=0;li<nlinks;li++){
|
||||
nsamples+=op_pcm_total(of,li)*op_channel_count(of,li);
|
||||
}
|
||||
/*Until we find another way to do the comparisons that solves the MATCH_TOL
|
||||
problem, disable this.*/
|
||||
#if 0
|
||||
bigassbuffer=_ogg_malloc(sizeof(*bigassbuffer)*nsamples);
|
||||
if(bigassbuffer==NULL){
|
||||
fprintf(stderr,
|
||||
"Buffer allocation failed. Seek offset detection disabled.\n");
|
||||
}
|
||||
#else
|
||||
bigassbuffer=NULL;
|
||||
#endif
|
||||
pcm_offset=op_pcm_tell(of);
|
||||
if(pcm_offset!=0){
|
||||
fprintf(stderr,"Initial PCM offset was not 0, got %li instead.!\n",
|
||||
(long)pcm_offset);
|
||||
nfailures++;
|
||||
}
|
||||
/*Disabling the linear scan for now.
|
||||
Only test on non-borken files!*/
|
||||
#if 0
|
||||
{
|
||||
op_sample smallerbuffer[120*48*8];
|
||||
ogg_int64_t pcm_print_offset;
|
||||
ogg_int64_t si;
|
||||
opus_int32 bitrate;
|
||||
int saw_hole;
|
||||
pcm_print_offset=pcm_offset-48000;
|
||||
bitrate=0;
|
||||
saw_hole=0;
|
||||
for(si=0;si<nsamples;){
|
||||
ogg_int64_t next_pcm_offset;
|
||||
opus_int32 next_bitrate;
|
||||
op_sample *buf;
|
||||
int buf_size;
|
||||
buf=bigassbuffer==NULL?smallerbuffer:bigassbuffer+si;
|
||||
buf_size=(int)OP_MIN(nsamples-si,
|
||||
(int)(sizeof(smallerbuffer)/sizeof(*smallerbuffer))),
|
||||
ret=op_read_native(of,buf,buf_size,&li);
|
||||
if(ret==OP_HOLE){
|
||||
/*Only warn once in a row.*/
|
||||
if(saw_hole)continue;
|
||||
saw_hole=1;
|
||||
/*This is just a warning.
|
||||
As long as the timestamps are still contiguous we're okay.*/
|
||||
fprintf(stderr,"\nHole in PCM data at sample %li\n",
|
||||
(long)pcm_offset);
|
||||
continue;
|
||||
}
|
||||
else if(ret<=0){
|
||||
fprintf(stderr,"\nFailed to read PCM data: %i\n",ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
saw_hole=0;
|
||||
/*If we have gaps in the PCM positions, seeking is not likely to work
|
||||
near them.*/
|
||||
next_pcm_offset=op_pcm_tell(of);
|
||||
if(pcm_offset+ret!=next_pcm_offset){
|
||||
fprintf(stderr,"\nGap in PCM offset: expecting %li, got %li\n",
|
||||
(long)(pcm_offset+ret),(long)next_pcm_offset);
|
||||
nfailures++;
|
||||
}
|
||||
pcm_offset=next_pcm_offset;
|
||||
si+=ret*op_channel_count(of,li);
|
||||
if(pcm_offset>=pcm_print_offset+48000){
|
||||
next_bitrate=op_bitrate_instant(of);
|
||||
if(next_bitrate>=0)bitrate=next_bitrate;
|
||||
fprintf(stderr,"\r%s... [%li left] (%0.3f kbps) ",
|
||||
bigassbuffer==NULL?"Scanning":"Loading",nsamples-si,bitrate/1000.0);
|
||||
pcm_print_offset=pcm_offset;
|
||||
}
|
||||
}
|
||||
ret=op_read_native(of,smallerbuffer,8,&li);
|
||||
if(ret<0){
|
||||
fprintf(stderr,"Failed to read PCM data: %i\n",ret);
|
||||
nfailures++;
|
||||
}
|
||||
if(ret>0){
|
||||
fprintf(stderr,"Read too much PCM data!\n");
|
||||
nfailures++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pcm_length=op_pcm_total(of,-1);
|
||||
size=op_raw_total(of,-1);
|
||||
fprintf(stderr,"\rLoaded (%0.3f kbps average). \n",
|
||||
op_bitrate(of,-1)/1000.0);
|
||||
fprintf(stderr,"Testing raw seeking to random places in %li bytes...\n",
|
||||
(long)size);
|
||||
max_seeks=0;
|
||||
for(i=0;i<NSEEK_TESTS;i++){
|
||||
long nseeks_tmp;
|
||||
opus_int64 byte_offset;
|
||||
nseeks_tmp=nreal_seeks;
|
||||
byte_offset=(opus_int64)(rand()/(double)RAND_MAX*size);
|
||||
fprintf(stderr,"\r\t%3i [raw position %li]... ",
|
||||
i,(long)byte_offset);
|
||||
ret=op_raw_seek(of,byte_offset);
|
||||
if(ret<0){
|
||||
fprintf(stderr,"\nSeek failed: %i.\n",ret);
|
||||
nfailures++;
|
||||
}
|
||||
if(i==28){
|
||||
i=28;
|
||||
}
|
||||
verify_seek(of,byte_offset,-1,pcm_length,bigassbuffer);
|
||||
nseeks_tmp=nreal_seeks-nseeks_tmp;
|
||||
max_seeks=nseeks_tmp>max_seeks?nseeks_tmp:max_seeks;
|
||||
}
|
||||
fprintf(stderr,"\rTotal seek operations: %li (%.3f per raw seek, %li maximum).\n",
|
||||
nreal_seeks,nreal_seeks/(double)NSEEK_TESTS,max_seeks);
|
||||
nreal_seeks=0;
|
||||
fprintf(stderr,"Testing exact PCM seeking to random places in %li "
|
||||
"samples (",(long)pcm_length);
|
||||
print_duration(stderr,pcm_length);
|
||||
fprintf(stderr,")...\n");
|
||||
max_seeks=0;
|
||||
for(i=0;i<NSEEK_TESTS;i++){
|
||||
ogg_int64_t pcm_offset2;
|
||||
long nseeks_tmp;
|
||||
nseeks_tmp=nreal_seeks;
|
||||
pcm_offset=(ogg_int64_t)(rand()/(double)RAND_MAX*pcm_length);
|
||||
fprintf(stderr,"\r\t%3i [PCM position %li]... ",
|
||||
i,(long)pcm_offset);
|
||||
ret=op_pcm_seek(of,pcm_offset);
|
||||
if(ret<0){
|
||||
fprintf(stderr,"\nSeek failed: %i.\n",ret);
|
||||
nfailures++;
|
||||
}
|
||||
pcm_offset2=op_pcm_tell(of);
|
||||
if(pcm_offset!=pcm_offset2){
|
||||
fprintf(stderr,"\nDeclared PCM position did not perfectly match "
|
||||
"request: requested %li, got %li.\n",
|
||||
(long)pcm_offset,(long)pcm_offset2);
|
||||
nfailures++;
|
||||
}
|
||||
verify_seek(of,-1,pcm_offset,pcm_length,bigassbuffer);
|
||||
nseeks_tmp=nreal_seeks-nseeks_tmp;
|
||||
max_seeks=nseeks_tmp>max_seeks?nseeks_tmp:max_seeks;
|
||||
}
|
||||
fprintf(stderr,"\rTotal seek operations: %li (%.3f per exact seek, %li maximum).\n",
|
||||
nreal_seeks,nreal_seeks/(double)NSEEK_TESTS,max_seeks);
|
||||
nreal_seeks=0;
|
||||
fprintf(stderr,"OK.\n");
|
||||
_ogg_free(bigassbuffer);
|
||||
}
|
||||
else{
|
||||
fprintf(stderr,"Input was not seekable.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
op_free(of);
|
||||
if(nfailures>0){
|
||||
fprintf(stderr,"FAILED: %li failure conditions encountered.\n",nfailures);
|
||||
}
|
||||
return nfailures!=0?EXIT_FAILURE:EXIT_SUCCESS;
|
||||
}
|
111
libsdl2_mixer/external/opusfile-0.10/examples/win32utf8.c
vendored
Normal file
111
libsdl2_mixer/external/opusfile-0.10/examples/win32utf8.c
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
#if defined(_WIN32)
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <wchar.h>
|
||||
/*We need the following two to set stdin/stdout to binary.*/
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_EXTRA_LEAN
|
||||
# include <windows.h>
|
||||
# include "win32utf8.h"
|
||||
|
||||
static char *utf16_to_utf8(const wchar_t *_src){
|
||||
char *dst;
|
||||
size_t len;
|
||||
size_t si;
|
||||
size_t di;
|
||||
len=wcslen(_src);
|
||||
dst=(char *)malloc(sizeof(*dst)*(3*len+1));
|
||||
if(dst==NULL)return dst;
|
||||
for(di=si=0;si<len;si++){
|
||||
unsigned c0;
|
||||
c0=_src[si];
|
||||
if(c0<0x80){
|
||||
/*Can be represented by a 1-byte sequence.*/
|
||||
dst[di++]=(char)c0;
|
||||
continue;
|
||||
}
|
||||
else if(c0<0x800){
|
||||
/*Can be represented by a 2-byte sequence.*/
|
||||
dst[di++]=(char)(0xC0|c0>>6);
|
||||
dst[di++]=(char)(0x80|c0&0x3F);
|
||||
continue;
|
||||
}
|
||||
else if(c0>=0xD800&&c0<0xDC00){
|
||||
unsigned c1;
|
||||
/*This is safe, because c0 was not 0 and _src is NUL-terminated.*/
|
||||
c1=_src[si+1];
|
||||
if(c1>=0xDC00&&c1<0xE000){
|
||||
unsigned w;
|
||||
/*Surrogate pair.*/
|
||||
w=((c0&0x3FF)<<10|c1&0x3FF)+0x10000;
|
||||
/*Can be represented by a 4-byte sequence.*/
|
||||
dst[di++]=(char)(0xF0|w>>18);
|
||||
dst[di++]=(char)(0x80|w>>12&0x3F);
|
||||
dst[di++]=(char)(0x80|w>>6&0x3F);
|
||||
dst[di++]=(char)(0x80|w&0x3F);
|
||||
si++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*Anything else is either a valid 3-byte sequence, an invalid surrogate
|
||||
pair, or 'not a character'.
|
||||
In the latter two cases, we just encode the value as a 3-byte
|
||||
sequence anyway (producing technically invalid UTF-8).
|
||||
Later error handling will detect the problem, with a better
|
||||
chance of giving a useful error message.*/
|
||||
dst[di++]=(char)(0xE0|c0>>12);
|
||||
dst[di++]=(char)(0x80|c0>>6&0x3F);
|
||||
dst[di++]=(char)(0x80|c0&0x3F);
|
||||
}
|
||||
dst[di++]='\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
typedef LPWSTR *(APIENTRY *command_line_to_argv_w_func)(LPCWSTR cmd_line,
|
||||
int *num_args);
|
||||
|
||||
/*Make a best-effort attempt to support UTF-8 on Windows.*/
|
||||
void win32_utf8_setup(int *_argc,const char ***_argv){
|
||||
HMODULE hlib;
|
||||
/*We need to set stdin/stdout to binary mode.
|
||||
This is unrelated to UTF-8 support, but it's platform specific and we need
|
||||
to do it in the same places.*/
|
||||
_setmode(_fileno(stdin),_O_BINARY);
|
||||
_setmode(_fileno(stdout),_O_BINARY);
|
||||
hlib=LoadLibraryA("shell32.dll");
|
||||
if(hlib!=NULL){
|
||||
command_line_to_argv_w_func command_line_to_argv_w;
|
||||
/*This function is only available on Windows 2000 or later.*/
|
||||
command_line_to_argv_w=(command_line_to_argv_w_func)GetProcAddress(hlib,
|
||||
"CommandLineToArgvW");
|
||||
if(command_line_to_argv_w!=NULL){
|
||||
wchar_t **argvw;
|
||||
int argc;
|
||||
argvw=(*command_line_to_argv_w)(GetCommandLineW(),&argc);
|
||||
if(argvw!=NULL){
|
||||
int ai;
|
||||
/*Really, I don't see why argc would ever differ from *_argc, but let's
|
||||
be paranoid.*/
|
||||
if(argc>*_argc)argc=*_argc;
|
||||
for(ai=0;ai<argc;ai++){
|
||||
char *argv;
|
||||
argv=utf16_to_utf8(argvw[ai]);
|
||||
if(argv!=NULL)(*_argv)[ai]=argv;
|
||||
}
|
||||
*_argc=argc;
|
||||
LocalFree(argvw);
|
||||
}
|
||||
}
|
||||
FreeLibrary(hlib);
|
||||
}
|
||||
# if defined(CP_UTF8)
|
||||
/*This does not work correctly in all environments (it breaks output in
|
||||
mingw32 for me), and requires a Unicode font (e.g., when using the default
|
||||
Raster font, even characters that are available in the font's codepage
|
||||
won't display properly).*/
|
||||
/*SetConsoleOutputCP(CP_UTF8);*/
|
||||
# endif
|
||||
}
|
||||
#endif
|
9
libsdl2_mixer/external/opusfile-0.10/examples/win32utf8.h
vendored
Normal file
9
libsdl2_mixer/external/opusfile-0.10/examples/win32utf8.h
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#if !defined(_win32utf8_H)
|
||||
# define _win32utf8_H (1)
|
||||
# if defined(_WIN32)
|
||||
|
||||
/*Make a best-effort attempt to support UTF-8 on Windows.*/
|
||||
void win32_utf8_setup(int *_argc,const char ***_argv);
|
||||
|
||||
# endif
|
||||
#endif
|
Reference in New Issue
Block a user