@@ -6,7 +6,7 @@
#include "music_gme.h"

#include "gme/gme.h"
#include "resample/sox_resample.h"
#include "resample/my_resample.h"

#include <stdio.h>

@@ -136,6 +136,12 @@ struct MUSIC_GME *GME_LoadSongRW(SDL_RWops *src, int trackNum)
strcpy(spcSpec->mus_copyright, musInfo->copyright);
gme_free_info( musInfo );

SDL_BuildAudioCVT(&spcSpec->cvt, AUDIO_S16, 2,
mixer.freq,
mixer.format,
mixer.channels,
mixer.freq);

return spcSpec;
}
return NULL;
@@ -180,18 +186,33 @@ int GME_playAudio(struct MUSIC_GME *music, Uint8 *stream, int len)
if(music==NULL) return 1;
if(music->game_emu==NULL) return 1;
if(music->playing==-1) return 1;
if( len<0 ) return 0;
int srgArraySize = len/music->cvt.len_ratio;
short buf[srgArraySize];
int srcLen = (int)((double)(len/2)/music->cvt.len_ratio);

char *err = (char*)gme_play( music->game_emu, srcLen, buf );
if( err != NULL)
{
Mix_SetError("GAME-EMU: %s", err);
return 0;
}
int dest_len = srcLen*2;

short buf[len];
gme_play( music->game_emu, len/2, buf );
Uint8*src = (Uint8*)buf;
if( music->cvt.needed ) {
music->cvt.len = dest_len;
music->cvt.buf = (Uint8*)buf;
SDL_ConvertAudio(&music->cvt);
dest_len = music->cvt.len_cvt;
}

if ( music->volume == MIX_MAX_VOLUME )
{
SDL_memcpy(stream, src, len);
SDL_memcpy(stream, (Uint8*)buf, dest_len);
} else {
SDL_MixAudio(stream, src, len, music->volume);
SDL_MixAudio(stream, (Uint8*)buf, dest_len, music->volume);
}
return 0;
return len-dest_len;
}

/* Stop playback of a stream previously started with GME_play() */
@@ -40,6 +40,7 @@ struct MUSIC_GME
char *mus_artist;
char *mus_album;
char *mus_copyright;
SDL_AudioCVT cvt;
};

/* Initialize the Ogg Vorbis player, with the given mixer settings
@@ -21,44 +21,107 @@

#ifdef MP3_MAD_MUSIC

#include <SDL2/SDL_stdinc.h>
#include <string.h>
#include <stdio.h>

#include "music_mad.h"
#include "libid3tag/id3tag.h"

#include "resample/sox_resample.h"

unsigned int mad_target_samplerate=44100;
void mad_fetchID3Tags(mad_data *mp3_mad, char* filePath)
{
if(filePath==NULL) return;
if(strlen(filePath)==0) return;

struct id3_file *tags = id3_file_open(filePath, ID3_FILE_MODE_READONLY);
if( tags ) {
struct id3_tag *tag= id3_file_tag(tags);

//Attempt to skip that dumb ID3 that causes junk begin on some MP3 files :-P
mp3_mad->src_begin_pos = tag->paddedsize;
SDL_RWseek(mp3_mad->src, tag->paddedsize, RW_SEEK_SET);

//Search for given frame by frame id
struct id3_frame *pFrame = id3_tag_findframe(tag,ID3_FRAME_TITLE,0);
if ( pFrame != NULL )
{
union id3_field field = pFrame->fields[1];
id3_ucs4_t const *pTemp = id3_field_getstrings(&field,0);
id3_latin1_t *pStrLatinl;
if ( pTemp != NULL ) {
pStrLatinl = id3_ucs4_latin1duplicate(pTemp);
mp3_mad->mus_title=(char *)SDL_malloc(sizeof(char)*strlen((char*)pStrLatinl)+1);
strcpy(mp3_mad->mus_title, (char*)pStrLatinl);
}
}
pFrame = id3_tag_findframe(tag,ID3_FRAME_ARTIST,0);
if ( pFrame != NULL )
{
union id3_field field = pFrame->fields[1];
id3_ucs4_t const *pTemp = id3_field_getstrings(&field,0);
id3_latin1_t *pStrLatinl;
if ( pTemp != NULL ) {
pStrLatinl = id3_ucs4_latin1duplicate(pTemp);
mp3_mad->mus_artist=(char *)SDL_malloc(sizeof(char)*strlen((char*)pStrLatinl)+1);
strcpy(mp3_mad->mus_artist, (char*)pStrLatinl);
}
}
pFrame = id3_tag_findframe(tag,ID3_FRAME_ALBUM,0);
if ( pFrame != NULL )
{
union id3_field field = pFrame->fields[1];
id3_ucs4_t const *pTemp = id3_field_getstrings(&field,0);
id3_latin1_t *pStrLatinl;
if ( pTemp != NULL ) {
pStrLatinl = id3_ucs4_latin1duplicate(pTemp);
mp3_mad->mus_album=(char *)SDL_malloc(sizeof(char)*strlen((char*)pStrLatinl)+1);
strcpy(mp3_mad->mus_album, (char*)pStrLatinl);
}
}
pFrame = id3_tag_findframe(tag, "TCOP",0);
if ( pFrame != NULL )
{
union id3_field field = pFrame->fields[1];
id3_ucs4_t const *pTemp = id3_field_getstrings(&field,0);
id3_latin1_t *pStrLatinl;
if ( pTemp != NULL ) {
pStrLatinl = id3_ucs4_latin1duplicate(pTemp);
mp3_mad->mus_copyright=(char *)SDL_malloc(sizeof(char)*strlen((char*)pStrLatinl)+1);
strcpy(mp3_mad->mus_copyright, (char*)pStrLatinl);
}
}
id3_file_close(tags);
}
}

mad_data *
mad_openFileRW(SDL_RWops *src, SDL_AudioSpec *mixer, int freesrc)
{
mad_data *mp3_mad;

mp3_mad = (mad_data *)SDL_malloc(sizeof(mad_data));
if (mp3_mad) {
mp3_mad->src = src;
mp3_mad->freesrc = freesrc;
mad_stream_init(&mp3_mad->stream);
mad_frame_init(&mp3_mad->frame);
mad_synth_init(&mp3_mad->synth);
mp3_mad->frames_read = 0;
mad_timer_reset(&mp3_mad->next_frame_start);
mp3_mad->volume = MIX_MAX_VOLUME;
mp3_mad->status = 0;
mp3_mad->output_begin = 0;
mp3_mad->output_end = 0;
mp3_mad->mixer = *mixer;
mp3_mad->mus_title = NULL;
mp3_mad->mus_album = NULL;
mp3_mad->mus_artist = NULL;
mp3_mad->mus_copyright = NULL;

mp3_mad->_resampler = NULL;

mad_target_samplerate=mixer->freq;
}
return mp3_mad;
mad_data *mp3_mad;

mp3_mad = (mad_data *)SDL_malloc(sizeof(mad_data));
if (mp3_mad) {
mp3_mad->src = src;
mp3_mad->src_begin_pos = 0;
mp3_mad->freesrc = freesrc;
mad_stream_init(&mp3_mad->stream);
mad_frame_init(&mp3_mad->frame);
mad_synth_init(&mp3_mad->synth);
mp3_mad->frames_read = 0;
mad_timer_reset(&mp3_mad->next_frame_start);
mp3_mad->volume = MIX_MAX_VOLUME;
mp3_mad->status = 0;
mp3_mad->output_begin = 0;
mp3_mad->output_end = 0;
mp3_mad->mixer = *mixer;
mp3_mad->mus_title = NULL;
mp3_mad->mus_album = NULL;
mp3_mad->mus_artist = NULL;
mp3_mad->mus_copyright = NULL;
MyResample_zero(&mp3_mad->resample);
}
return mp3_mad;
}

void
@@ -83,9 +146,6 @@ mad_closeFile(mad_data *mp3_mad)
if( mp3_mad->mus_copyright ) {
SDL_free( mp3_mad->mus_copyright );
}
if( mp3_mad->_resampler ) {
SoxResamplerFree( mp3_mad->_resampler );
}
SDL_free(mp3_mad);
}

@@ -224,22 +284,21 @@ decode_frame(mad_data *mp3_mad) {

if ((mp3_mad->status & MS_cvt_decoded) == 0)
{
mp3_mad->status |= MS_cvt_decoded;

/*Temporary don't resample any MP3's*/
//int resampleNeed=(mp3_mad->frame.header.samplerate!=mad_target_samplerate);

/* The first frame determines some key properties of the stream.
In particular, it tells us enough to set up the convert
structure now. */
//int framerate_source=mp3_mad->frame.header.samplerate;
//mp3_mad->frame.header.samplerate = mad_target_samplerate;

SDL_BuildAudioCVT(&mp3_mad->cvt, AUDIO_S16, pcm->channels,
mp3_mad->frame.header.samplerate, mp3_mad->mixer.format, mp3_mad->mixer.channels, mp3_mad->mixer.freq);

//mp3_mad->frame.header.samplerate=framerate_source;
//mp3_mad->cvt.needed = resampleNeed;
mp3_mad->status |= MS_cvt_decoded;
/* The first frame determines some key properties of the stream.
In particular, it tells us enough to set up the convert
structure now. */
MyResample_init(&mp3_mad->resample,
mp3_mad->frame.header.samplerate,
mp3_mad->mixer.freq,
pcm->channels,
AUDIO_S16);

SDL_BuildAudioCVT(&mp3_mad->cvt, AUDIO_S16, pcm->channels,
mp3_mad->mixer.freq/*mp3_mad->frame.header.samplerate*/,// <-- HACK: Avoid SDL's internal resamplers usage
mp3_mad->mixer.format,
mp3_mad->mixer.channels,
mp3_mad->mixer.freq);
}

/* pcm->samplerate contains the sampling frequency */
@@ -281,106 +340,113 @@ mad_getSamples(mad_data *mp3_mad, Uint8 *stream, int len) {

out = stream;
bytes_remaining = len;
while (bytes_remaining > 0) {
if (mp3_mad->output_end == mp3_mad->output_begin) {
/* We need to get a new frame. */
mp3_mad->output_begin = 0;
mp3_mad->output_end = 0;
if (!read_next_frame(mp3_mad))

while(bytes_remaining > 0)
{
/************Use reserved bytes if stored**************/
if(mp3_mad->resample.buf_len > 0)
{
if ((mp3_mad->status & MS_error_flags) != 0)
num_bytes = mp3_mad->resample.buf_len;

if (bytes_remaining < num_bytes)
{
num_bytes = bytes_remaining;
}

if(num_bytes>=0)
{
if (mp3_mad->volume == MIX_MAX_VOLUME) {
SDL_memcpy(out, mp3_mad->resample.buf, num_bytes);
} else {
SDL_MixAudio(out, mp3_mad->resample.buf, num_bytes, mp3_mad->volume);
}
}
out += num_bytes;

MyResample_dequeueBytes(&mp3_mad->resample, num_bytes);

bytes_remaining -= num_bytes;
}
else /************Fetch for a new bytes**************/
{
if (mp3_mad->output_end == mp3_mad->output_begin)
{
/* Couldn't read a frame; either an error condition or
end-of-file. Stop. */
SDL_memset(out, 0, bytes_remaining);
mp3_mad->status &= ~MS_playing;
return bytes_remaining;
}
} else {
decode_frame(mp3_mad);
/* We need to get a new frame. */
mp3_mad->output_begin = 0;
mp3_mad->output_end = 0;
if (!read_next_frame(mp3_mad))
{
if ((mp3_mad->status & MS_error_flags) != 0)
{
/* Couldn't read a frame; either an error condition or
end-of-file. Stop. */
SDL_memset(out, 0, bytes_remaining);
mp3_mad->status &= ~MS_playing;
return bytes_remaining;
}
} else {
decode_frame(mp3_mad);

/* Now convert the frame data to the appropriate format for
output. */
mp3_mad->cvt.buf = mp3_mad->output_buffer;
mp3_mad->cvt.len = mp3_mad->output_end;
/* Now convert the frame data to the appropriate format for
output. */
mp3_mad->cvt.buf = mp3_mad->output_buffer;
mp3_mad->cvt.len = mp3_mad->output_end;

if(mp3_mad->cvt.len_ratio>0)
mp3_mad->output_end = (int)(mp3_mad->output_end * mp3_mad->cvt.len_ratio);
if(mp3_mad->cvt.len_ratio>0)
mp3_mad->output_end = (int)(mp3_mad->output_end * mp3_mad->cvt.len_ratio);

/*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
/*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/

if( mp3_mad->cvt.needed>0 )
{
/*
int num_bytes_out =
(int) ( (double)(mp3_mad->cvt.len)*((double)mad_target_samplerate/(double)mp3_mad->frame.header.samplerate));
if(mp3_mad->_resampler==NULL)
if( (mp3_mad->resample.needed > 0) || (mp3_mad->cvt.needed > 0) )
{
mp3_mad->_resampler = SoxResamplerINIT(mp3_mad->frame.header.samplerate,
mad_target_samplerate, mp3_mad->synth.pcm.channels, num_bytes_out);
}
if(mp3_mad->_resampler && num_bytes_out>0)
{
Uint8 outBuff[num_bytes_out];
mp3_mad->cvt.len_ratio = mp3_mad->_resampler->factor;
mp3_mad->cvt.rate_incr = mp3_mad->_resampler->factor;
Uint8* inBuff = (Uint8*)(mp3_mad->output_buffer+mp3_mad->output_begin);
int obytes=0;
SoxResamplerProcess( mp3_mad->_resampler, inBuff, num_bytes, &outBuff, &obytes );
mp3_mad->cvt.len_cvt = obytes;
Uint8* copyTo = mp3_mad->output_buffer+mp3_mad->output_begin;
Uint8* copyFrom=outBuff;
while( num_bytes_out-- )
//*****ORIGINAL*****
//SDL_ConvertAudio(&mp3_mad->cvt);

//*******NEW********
MyResample_addSource(&mp3_mad->resample, mp3_mad->output_buffer+mp3_mad->output_begin, mp3_mad->cvt.len);
mp3_mad->output_begin += mp3_mad->cvt.len;
mp3_mad->output_end = mp3_mad->cvt.len;
mp3_mad->cvt.buf = mp3_mad->resample.buf;
if(mp3_mad->resample.needed)
{
*copyTo++ = *copyFrom++;
MyResample_Process(&mp3_mad->resample);
}
mp3_mad->output_end = copyTo - mp3_mad->output_buffer;
}*/
SDL_ConvertAudio(&mp3_mad->cvt);
//double Ration_______did = mp3_mad->cvt.rate_incr;
//double Ration__shouldBe = (double)mad_target_samplerate/(double)mp3_mad->frame.header.samplerate;
//mp3_mad->cvt.len_cvt = mp3_mad->cvt.len;
//SDL_Upsample_S16LSB_2c_kokoko(&mp3_mad->cvt, mp3_mad->cvt.src_format);
mp3_mad->output_end = mp3_mad->cvt.len_cvt;
}
else
{
mp3_mad->cvt.len_cvt = mp3_mad->cvt.len;
mp3_mad->cvt.len_mult = 1;
mp3_mad->cvt.len_ratio = 1.0;
mp3_mad->cvt.needed = 0;
mp3_mad->cvt.rate_incr = 1.0;
if( mp3_mad->cvt.needed > 0 ) {
mp3_mad->cvt.len = mp3_mad->resample.buf_len;
SDL_ConvertAudio(&mp3_mad->cvt);
mp3_mad->resample.buf_len = mp3_mad->cvt.len_cvt;
}
continue;//Do usage of backup samples now!
}
else
{
mp3_mad->cvt.len_cvt = mp3_mad->cvt.len;
mp3_mad->cvt.len_mult = 1;
mp3_mad->cvt.len_ratio = 1.0;
mp3_mad->cvt.needed = 0;
mp3_mad->cvt.rate_incr = 1.0;
}
}
}
}
}

num_bytes = mp3_mad->output_end - mp3_mad->output_begin;

// FILE * outshit = fopen("C:/_Repos/PGE-Project/bin-w32/outshit.raw", "ab");
// fwrite((char*)(mp3_mad->output_buffer + mp3_mad->output_begin), 1, num_bytes, outshit);
// fflush(outshit);
// fclose(outshit);
num_bytes = mp3_mad->output_end - mp3_mad->output_begin;

if (bytes_remaining < num_bytes) {
num_bytes = bytes_remaining;
}
if(num_bytes>=0)
{
if (mp3_mad->volume == MIX_MAX_VOLUME) {
SDL_memcpy(out, mp3_mad->output_buffer + mp3_mad->output_begin, num_bytes);
} else {
SDL_MixAudio(out, mp3_mad->output_buffer + mp3_mad->output_begin,
num_bytes, mp3_mad->volume);
}
if (bytes_remaining < num_bytes) {
num_bytes = bytes_remaining;
}
#ifdef DebugMAD
writeToLogMad("a", 15, "");
#endif
out += num_bytes;
mp3_mad->output_begin += num_bytes;
bytes_remaining -= num_bytes;
if(num_bytes>=0)
{
if (mp3_mad->volume == MIX_MAX_VOLUME) {
SDL_memcpy(out, mp3_mad->output_buffer + mp3_mad->output_begin, num_bytes);
} else {
SDL_MixAudio(out, mp3_mad->output_buffer + mp3_mad->output_begin,
num_bytes, mp3_mad->volume);
}
}
out += num_bytes;
mp3_mad->output_begin += num_bytes;
bytes_remaining -= num_bytes;
}
}
return 0;
}
@@ -407,7 +473,7 @@ mad_seek(mad_data *mp3_mad, double position) {
mp3_mad->output_begin = 0;
mp3_mad->output_end = 0;

SDL_RWseek(mp3_mad->src, 0, RW_SEEK_SET);
SDL_RWseek(mp3_mad->src, mp3_mad->src_begin_pos, RW_SEEK_SET);
}

/* Now we have to skip frames until we come to the right one.
@@ -25,6 +25,7 @@
#include <SDL2/SDL_rwops.h>
#include <SDL2/SDL_audio.h>
#include "SDL_mixer_ext.h"
#include "resample/my_resample.h"

#define MAD_INPUT_BUFFER_SIZE (5*8192)
#define MAD_OUTPUT_BUFFER_SIZE 8192
@@ -44,6 +45,8 @@ struct SoxResampler;

typedef struct {
SDL_RWops *src;
//! Begin position at begin of file, 0 by default, It exists here, because need to don't feed libMAD with ID3s which causes junk at begin!
int src_begin_pos;
int freesrc;
struct mad_stream stream;
struct mad_frame frame;
@@ -63,9 +66,11 @@ typedef struct {
char *mus_artist;
char *mus_album;
char *mus_copyright;
struct SoxResampler* _resampler;
struct MyResampler resample;
} mad_data;

void mad_fetchID3Tags(mad_data *mp3_mad, char* filePath);

mad_data *mad_openFileRW(SDL_RWops *src, SDL_AudioSpec *mixer, int freesrc);
void mad_closeFile(mad_data *mp3_mad);

@@ -149,6 +149,8 @@ struct MUSIC_MIDIADL *ADLMIDI_LoadSongRW(SDL_RWops *src)
adlMidi->volume=MIX_MAX_VOLUME;
adlMidi->mus_title=NULL;

SDL_BuildAudioCVT(&adlMidi->cvt, AUDIO_S16, 2, mixer.freq, mixer.format, mixer.channels, mixer.freq);

return adlMidi;
}
return NULL;
@@ -197,33 +199,32 @@ int ADLMIDI_playAudio(struct MUSIC_MIDIADL *music, Uint8 *stream, int len)
if(music==NULL) return 0;
if(music->adlmidi==NULL) return 0;
if(music->playing==-1) return 0;
len -= len%2;//Avoid non-odd sample requests
if( len<0 ) return 0;
int srgArraySize = len/music->cvt.len_ratio;
short buf[srgArraySize];
int srcLen = (int)((double)(len/2)/music->cvt.len_ratio);

int buf[len];
int gottenLen = adl_play( music->adlmidi, len/2, buf );
int gottenLen = adl_play( music->adlmidi, srcLen, buf );
if(gottenLen<=0)
{
return 0;
}
int dest_len = gottenLen*2;
Uint8 dst[len];
short* dout = (short*)dst;
int* din = buf;
int i;
for(i=0; i<dest_len; i+=2)
{
*dout = (short)(*din);
dout++; din++;

if( music->cvt.needed ) {
music->cvt.len = dest_len;
music->cvt.buf = (Uint8*)buf;
SDL_ConvertAudio(&music->cvt);
dest_len = music->cvt.len_cvt;
}

if( music->volume == MIX_MAX_VOLUME )
{
SDL_memcpy( stream, &dst, dest_len );
SDL_memcpy( stream, (Uint8*)buf, dest_len );
} else {
SDL_MixAudio( stream, dst, dest_len, music->volume);
SDL_MixAudio( stream, (Uint8*)buf, dest_len, music->volume);
}
return len-(gottenLen*2);
return len-dest_len;
}

/* Stop playback of a stream previously started with ADLMIDI_play() */
@@ -36,6 +36,7 @@ struct MUSIC_MIDIADL
int volume;
int gme_t_sample_rate;
char *mus_title;
SDL_AudioCVT cvt;
};

/*Setup editing functions (changes applying on file reopening)*/
@@ -96,6 +96,8 @@ OGG_music *OGG_new_RW(SDL_RWops *src, int freesrc)
music->mus_album=NULL;
music->mus_copyright=NULL;

MyResample_zero(&music->resample);

music->loop = -1;
music->loop_start = 0;
music->loop_end = 0;
@@ -171,7 +173,7 @@ OGG_music *OGG_new_RW(SDL_RWops *src, int freesrc)
(music->loop_end > 0)&&
(music->loop_start < music->loop_end) &&
(music->loop_start < ov_pcm_total(&music->vf,-1))&&
(music->loop_end < ov_pcm_total(&music->vf,-1)) )
(music->loop_end <= ov_pcm_total(&music->vf,-1)) )
{
music->loop=1;
vorbis_info *vi;
@@ -216,13 +218,14 @@ static void OGG_getsome(OGG_music *music)
len = vorbis.ov_read(&music->vf, data, sizeof(data), &section);
#else
len = vorbis.ov_read(&music->vf, data, sizeof(data), 0, 2, 1, &section);
ogg_int64_t pcmpos=ov_pcm_tell(&music->vf);
if( (music->loop==1) && ( pcmpos > music->loop_end ) )
#endif
ogg_int64_t pcmpos = ov_pcm_tell(&music->vf);
if( (music->loop==1) && ( pcmpos >= music->loop_end ) )
{
len -= ((pcmpos-music->loop_end)*music->loop_len_ch)*2;
ov_pcm_seek(&music->vf, music->loop_start);
}
#endif

if ( len <= 0 ) {
if ( len == 0 ) {
music->playing = 0;
@@ -234,21 +237,39 @@ static void OGG_getsome(OGG_music *music)
vorbis_info *vi;

vi = vorbis.ov_info(&music->vf, -1);
SDL_BuildAudioCVT(cvt, AUDIO_S16, vi->channels, vi->rate,
mixer.format,mixer.channels,mixer.freq);
MyResample_init(&music->resample,
vi->rate,
mixer.freq,
vi->channels,
AUDIO_S16);
SDL_BuildAudioCVT(cvt,
AUDIO_S16,
vi->channels,
mixer.freq/*vi->rate HACK: Don't use SDL's resamplers*/,
mixer.format,
mixer.channels,
mixer.freq);
if ( cvt->buf ) {
SDL_free(cvt->buf);
}
cvt->buf = (Uint8 *)SDL_malloc(sizeof(data)*cvt->len_mult);
cvt->buf = (Uint8 *)SDL_malloc(sizeof(data) * cvt->len_mult * music->resample.ratio);
music->section = section;
}

if ( cvt->buf ) {
SDL_memcpy(cvt->buf, data, len);
if ( cvt->needed ) {
cvt->len = len;
SDL_ConvertAudio(cvt);
if( music->resample.needed ) {
MyResample_addSource(&music->resample, data, len);
MyResample_Process(&music->resample);
SDL_memcpy(cvt->buf, music->resample.buf, music->resample.buf_len);
cvt->len = music->resample.buf_len;
cvt->len_cvt = music->resample.buf_len;
} else {
cvt->len = len;
cvt->len_cvt = len;
SDL_memcpy(cvt->buf, data, len);
}
if ( cvt->needed ) {
SDL_ConvertAudio(cvt);
}
music->len_available = music->cvt.len_cvt;
music->snd_available = music->cvt.buf;
@@ -33,6 +33,8 @@
#include <vorbis/vorbisfile.h>
#endif

#include "resample/my_resample.h"

typedef struct {
SDL_RWops *src;
int freesrc;
@@ -54,6 +56,7 @@ typedef struct {
char *mus_artist;
char *mus_album;
char *mus_copyright;
struct MyResampler resample;
} OGG_music;

/* Initialize the Ogg Vorbis player, with the given mixer settings

This file was deleted.

This file was deleted.

@@ -0,0 +1,362 @@
/*
SDL_mixer_ext: An extended audio mixer library, forked from SDL_mixer
Copyright (C) 2014-2016 Vitaly Novichkov <admin@wohlnet.ru>
SDL_mixer: An audio mixer library based on the SDL library
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

/* $Id$ */

/* This file supports safe and better resampling than built-in with SDL.
Currently works for Signed 16-bit audio only, there are would work slower than SDL's */

#include "my_resample.h"

static void SDL_Upsample_S16LSB_1c_KoKoKo(struct MyResampler *res)
{
#if DEBUG_CONVERT
fprintf(stderr, "Upsample arbitrary (x%f) AUDIO_U16LSB, 1 channel.\n", cvt->rate_incr);
#endif
const int dstsize = (int)(((double)res->buf_len/2.0) * res->ratio) * 2;
short *s_src = (Uint16 *) (res->buf);
short s_dst[dstsize];

register double p_src=0.0, q_dst=0.0, r_ps=0.0, s_size=res->buf_len, d_size=dstsize;
int oldSam0 = (int)p_src;
short old0 = s_src[oldSam0];
double offset=1.0/res->ratio;

//Resample it!
for(p_src=0.f, q_dst=0.f, r_ps=0.f; (p_src < s_size) && (q_dst < d_size); q_dst+=1.f )
{
s_dst[(int)q_dst] = old0;
r_ps += offset;
if( r_ps >= 1.0 )
{
p_src += 1.0;
r_ps -= 1.0;
oldSam0 = (int)p_src;
old0 = s_src[oldSam0];
}
}

int i;
for(i=0;i<dstsize;++i) s_src[i] = s_dst[i];
res->buf_len = dstsize;
}

static void SDL_Downsample_S16LSB_1c_KoKoKo(struct MyResampler *res)
{
#if DEBUG_CONVERT
fprintf(stderr, "Upsample arbitrary (x%f) AUDIO_U16LSB, 1 channel.\n", cvt->rate_incr);
#endif
const int dstsize = (int)(((double)res->buf_len/2.0) * res->ratio) * 2;
short *s_src = (Uint16 *) (res->buf);
short s_dst[dstsize];

register double p_src=0.0, q_dst=0.0, r_ps=0.0, s_size=res->buf_len, d_size=dstsize;
int oldSam0 = (int)p_src;
short old0 = s_src[oldSam0];
s_dst[(int)q_dst] = old0;

double offset=res->ratio;
//Resample it!
for(p_src=0.f, q_dst=0.f, r_ps=0.f; (p_src < s_size) && (q_dst < d_size); p_src+=1.f )
{
r_ps += offset;
if( r_ps >= 1.0 )
{
oldSam0 = (int)p_src;
old0 = s_src[oldSam0];
s_dst[(int)q_dst] = old0;
q_dst += 1.0;
r_ps -= 1.0;
}
}

int i;
for(i=0;i<dstsize;++i) s_src[i] = s_dst[i];
res->buf_len = dstsize;
}


static void SDL_Upsample_S16LSB_2c_KoKoKo(struct MyResampler *res)
{
#if DEBUG_CONVERT
fprintf(stderr, "Upsample arbitrary (x%f) AUDIO_S16LSB, 2 channels.\n", cvt->rate_incr);
#endif
const int dstsize = (int)(((double)res->buf_len/4.0) * res->ratio) * 4;
short *s_src = (Uint16 *) (res->buf);
short s_dst[dstsize];

register double p_src=0.0, q_dst=0.0, r_ps=0.0, s_size=res->buf_len, d_size=dstsize;
int oldSam1 = (int)p_src+1;
int oldSam0 = (int)p_src;
short old1 = s_src[oldSam1];
short old0 = s_src[oldSam0];
double offset=1.0/res->ratio;

//Resample it!
for(p_src=0.f, q_dst=0.f, r_ps=0.f; (p_src < s_size) && (q_dst < d_size); q_dst+=2.f )
{
s_dst[(int)q_dst+1] = old1;
s_dst[(int)q_dst] = old0;
r_ps += offset;
if( r_ps >= 1.0 )
{
p_src += 2.0;
r_ps -= 1.0;
oldSam1 = (int)p_src+1;
oldSam0 = (int)p_src;
old1 = s_src[oldSam1];
old0 = s_src[oldSam0];
}
}

int i;
for(i=0;i<dstsize;++i) s_src[i] = s_dst[i];
res->buf_len = dstsize;
}

static void SDL_Downsample_S16LSB_2c_KoKoKo(struct MyResampler *res)
{
#if DEBUG_CONVERT
fprintf(stderr, "Upsample arbitrary (x%f) AUDIO_S16LSB, 2 channels.\n", cvt->rate_incr);
#endif
const int dstsize = (int)(((double)res->buf_len/4.0) * res->ratio) * 4;
short *s_src = (Uint16 *) (res->buf);
short s_dst[dstsize];

register double p_src=0.0, q_dst=0.0, r_ps=0.0, s_size=res->buf_len, d_size=dstsize;
int oldSam1 = (int)p_src+1;
int oldSam0 = (int)p_src;
short old1 = s_src[oldSam1];
short old0 = s_src[oldSam0];
s_dst[(int)q_dst+1] = old1;
s_dst[(int)q_dst] = old0;

double offset = res->ratio;
//Resample it!
for(p_src=0.f, q_dst=0.f, r_ps=0.f; (p_src < s_size) && (q_dst < d_size); p_src+=2.f )
{
r_ps += offset;
if( r_ps >= 1.0 )
{
oldSam1 = (int)p_src+1;
oldSam0 = (int)p_src;
old1 = s_src[oldSam1];
old0 = s_src[oldSam0];
s_dst[(int)q_dst+1] = old1;
s_dst[(int)q_dst] = old0;
q_dst += 2.0;
r_ps -= 1.0;
}
}

int i;
for(i=0;i<dstsize;++i) s_src[i] = s_dst[i];
res->buf_len = dstsize;
}


//Upsample ANY number of channels
static void SDL_Upsample_S16LSB_Xc_KoKoKo(struct MyResampler *res)
{
#if DEBUG_CONVERT
fprintf(stderr, "Upsample arbitrary (x%f) AUDIO_S16LSB, %i channels.\n", res->ratio, res->channels );
#endif

int channels = res->channels;
double channells_f = (double)channels;
int chan_coeff=2*res->channels;

const int dstsize = (int)(((double)res->buf_len/chan_coeff) * res->ratio) * chan_coeff;
short *s_src = (Uint16 *) (res->buf);
short s_dst[dstsize];

register double p_src=0.0, q_dst=0.0, r_ps=0.0, s_size=res->buf_len, d_size=dstsize;

int i;
int oldSam[channels];
short old[channels];
for(i=0;i<channels;++i)
{
oldSam[i] = (int)p_src+i;
old[i] = s_src[oldSam[i]];
}

double offset=1.0/res->ratio;

//Resample it!
for(p_src=0.f, q_dst=0.f, r_ps=0.f; (p_src < s_size) && (q_dst < d_size); q_dst+=channells_f )
{
for(i=0;i<channels;++i)
s_dst[(int)q_dst+i] = old[i];
r_ps += offset;
if( r_ps >= 1.0 )
{
p_src += channells_f;
r_ps -= 1.0;
for(i=0;i<channels;i++)
{
oldSam[i] = (int)p_src+i;
old[i] = s_src[oldSam[i]];
}
}
}

for(i=0;i<dstsize;++i) s_src[i] = s_dst[i];
res->buf_len = dstsize;
}

//Downsample ANY number of channels
static void SDL_Downsample_S16LSB_Xc_KoKoKo(struct MyResampler *res)
{
#if DEBUG_CONVERT
fprintf(stderr, "Upsample arbitrary (x%f) AUDIO_S16LSB, %i channels.\n", res->ratio, res->channels );
#endif
if(res->channels<=0) return;

int channels = res->channels;
double channells_f = (double)channels;
int chan_coeff=2*res->channels;

const int dstsize = (int)(((double)res->buf_len/(double)chan_coeff) * res->ratio) * chan_coeff;
short *s_src = (Uint16 *) (res->buf);
short s_dst[dstsize];

register double p_src=0.0, q_dst=0.0, r_ps=0.0, s_size=res->buf_len, d_size=dstsize;

int i=0;
int oldSam[channels];
short old[channels];

for(i=0; i<channels; ++i)
{
oldSam[i] = (int)p_src+i;
old[i] = s_src[oldSam[i]];
s_dst[(int)q_dst+i] = old[i];
}

double offset = res->ratio;

//Resample it!
for(p_src=0.f, q_dst=0.f, r_ps=0.f; (p_src < s_size) && (q_dst < d_size); p_src+=channells_f )
{
r_ps += offset;
if( r_ps >= 1.0 )
{
for(i=0;i<channels;++i)
{
oldSam[i] = (int)p_src+1;
old[i] = s_src[oldSam[i]];
s_dst[(int)q_dst+i] = old[i];
}
q_dst += channells_f;
r_ps -= 1.0;
}
}

for(i=0;i<dstsize;++i) s_src[i] = s_dst[i];
res->buf_len = dstsize;
}

static void doNothing(struct MyResampler *res) {
(void)res;
}

void MyResample_init(struct MyResampler *res, int rate_in, int rate_out , int channels, SDL_AudioFormat format)
{
(void)format; // Temporary not needed :-P
res->needed = (rate_in != rate_out);
res->ratio = (double)rate_out/(double)rate_in;
res->buf_len=0;
res->channels=channels;
res->filter = &doNothing;
if(res->needed) {
if(res->ratio > 1.0)
{
switch(res->channels)
{
case 1://Upsample mono stream
res->filter = &SDL_Upsample_S16LSB_1c_KoKoKo;break;
case 2://Upsample stereo stream
res->filter = &SDL_Upsample_S16LSB_2c_KoKoKo;break;
default://Upsample stream with X channels number
res->filter = &SDL_Upsample_S16LSB_Xc_KoKoKo;break;
}
} else {
switch(res->channels)
{
case 1://Downsample mono stream
res->filter = &SDL_Downsample_S16LSB_1c_KoKoKo;break;
case 2://Downsample stereo stream
res->filter = &SDL_Downsample_S16LSB_2c_KoKoKo;break;
default://Downsample stream with X channels number
res->filter = &SDL_Downsample_S16LSB_Xc_KoKoKo;break;
}
}
}
}

void MyResample_addSource(struct MyResampler *res, Uint8* in_buffer, int in_len)
{
SDL_memcpy(res->buf, in_buffer, in_len);
res->buf_len = in_len;
}

void MyResample_Process(struct MyResampler *res)
{
if(!res) return;
if(res->needed==0) return;
if(res->buf_len==0) return;

res->filter(res);

}

void MyResample_dequeueBytes(struct MyResampler *res, int numbytes)
{
if( (res->buf_len-numbytes) > 0 )
{ //Move tail of buffer into begin of array
int i=numbytes;
char *dst = &res->buf[0];
char *src = &res->buf[i];
for(; i<res->buf_len;++i)
*dst++ = *src++;
res->buf_len -= numbytes;
} else {
res->buf_len = 0;
}
}

void MyResample_clear(struct MyResampler *res)
{
res->buf_len = 0;
}

void MyResample_zero(struct MyResampler *res)
{
res->buf_len = 0;
res->channels = 2;
res->ratio = 1.0;
res->needed = 0;
res->filter = &doNothing;
}
@@ -0,0 +1,54 @@
/*
SDL_mixer_ext: An extended audio mixer library, forked from SDL_mixer
Copyright (C) 2014-2016 Vitaly Novichkov <admin@wohlnet.ru>
SDL_mixer: An audio mixer library based on the SDL library
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

# ifndef RESAMPLE_H
# define RESAMPLE_H

#include "SDL_mixer_ext.h"

#define MyResampler_BUFFER_SIZE 102400

struct MyResampler
{
int needed;
double ratio;
int buf_len;
int channels;
Uint8 buf[MyResampler_BUFFER_SIZE];//100 KB for backup stuff;
void (*filter)(struct MyResampler *res);
};

void MyResample_zero(struct MyResampler *res);

void MyResample_init(struct MyResampler *res, int rate_in, int rate_out, int channels, SDL_AudioFormat format);

void MyResample_addSource(struct MyResampler *res, Uint8* in_buffer, int in_len);

void MyResample_Process(struct MyResampler *res);

void MyResample_dequeueBytes(struct MyResampler *res, int numbytes);

void MyResample_clear(struct MyResampler *res);

# endif

This file was deleted.

This file was deleted.

@@ -146,6 +146,7 @@ WAVStream *WAVStream_LoadSong_RW(SDL_RWops *src, int freesrc)
SDL_zerop(wave);
wave->src = src;
wave->freesrc = freesrc;
MyResample_zero(&wave->resample);

magic = SDL_ReadLE32(src);
if (magic == RIFF || magic == WAVE) {
@@ -159,9 +160,20 @@ WAVStream *WAVStream_LoadSong_RW(SDL_RWops *src, int freesrc)
WAVStream_FreeSong(wave);
return(NULL);
}
SDL_BuildAudioCVT(&wave->cvt,
wave->spec.format, wave->spec.channels, wave->spec.freq,
mixer.format, mixer.channels, mixer.freq);
if(wave->spec.format==AUDIO_S16) {//Build resampler for Signed-16 PCM files only!
MyResample_init(&wave->resample,
wave->spec.freq,
mixer.freq,
mixer.channels,
AUDIO_S16);
SDL_BuildAudioCVT(&wave->cvt,
wave->spec.format, wave->spec.channels, mixer.freq,
mixer.format, mixer.channels, mixer.freq);
} else { //Overwise, use SDL's shitty resamplers
SDL_BuildAudioCVT(&wave->cvt,
wave->spec.format, wave->spec.channels, wave->spec.freq,
mixer.format, mixer.channels, mixer.freq);
}
} else {
SDL_OutOfMemory();
return(NULL);
@@ -190,7 +202,7 @@ static int PlaySome(Uint8 *stream, int len)
Sint64 loop_start;
Sint64 loop_stop;
int i;
int consumed;
int consumed=0;

pos = SDL_RWtell(music->src);
stop = music->stop;
@@ -210,51 +222,114 @@ static int PlaySome(Uint8 *stream, int len)
loop = NULL;
}

if (music->cvt.needed) {
int original_len;
int bytes_remaining = len;
Uint8*out = stream;
int isEnd=0;

while( bytes_remaining>0 ) {

original_len = (int)((double)len/music->cvt.len_ratio);
if (music->cvt.len != original_len) {
int worksize;
if (music->cvt.buf != NULL) {
SDL_free(music->cvt.buf);
if(music->resample.buf_len > 0) {
int numBytes = music->resample.buf_len;
if(bytes_remaining < numBytes)
{
numBytes = bytes_remaining;
}
worksize = original_len*music->cvt.len_mult;
music->cvt.buf=(Uint8 *)SDL_malloc(worksize);
if (music->cvt.buf == NULL) {
SDL_MixAudio(out, music->resample.buf, numBytes, wavestream_volume);
out+=numBytes;
bytes_remaining -= numBytes;
consumed += numBytes;
MyResample_dequeueBytes(&music->resample, numBytes);
if((isEnd==1) && (music->resample.buf_len == 0))
{
bytes_remaining = 0;
}
}
else
if(music->cvt.needed || music->resample.needed) {
int original_len;

original_len = len;//(int)((double)len/(music->cvt.len_ratio*music->resample.ratio));
if(original_len<=0) {
return 0;
}
if (music->cvt.len != original_len) {
int worksize;
if (music->cvt.buf != NULL) {
SDL_free(music->cvt.buf);
music->cvt.buf = NULL;
}
worksize = original_len*music->cvt.len_ratio*music->resample.ratio;
if(original_len > worksize)
worksize = original_len;
music->cvt.buf=(Uint8 *)SDL_malloc(worksize);
if (music->cvt.buf == NULL) {
return 0;
}
music->cvt.len = original_len;
}
if ((stop - pos) < original_len) {
original_len = (int)(stop - pos);
}

original_len = SDL_RWread(music->src, music->cvt.buf, 1, original_len);
if(original_len < len) {
isEnd=1;
}

if (loop && SDL_RWtell(music->src) >= stop) {
if (loop->current_play_count == 1) {
loop->active = SDL_FALSE;
isEnd=1;
} else {
if (loop->current_play_count > 0) {
--loop->current_play_count;
}
SDL_RWseek(music->src, loop_start, RW_SEEK_SET);
music->resample.buf_len=0;
}
}

/* At least at the time of writing, SDL_ConvertAudio()
does byte-order swapping starting at the end of the
buffer. Thus, if we are reading 16-bit samples, we
had better make damn sure that we get an even
number of bytes, or we'll get garbage.
*/
if ((music->cvt.src_format & 0x0010) && (original_len & 1)) {
original_len--;
}

music->cvt.len = original_len;
MyResample_addSource(&music->resample, music->cvt.buf, original_len);
if(music->resample.needed)
{
MyResample_Process(&music->resample);
//SDL_memcpy(music->cvt.buf, music->resample.buf, music->resample.buf_len);
}
music->cvt.len = music->resample.buf_len;
music->cvt.len_cvt = music->resample.buf_len;
if(music->cvt.needed) {
Uint8 *orig = music->cvt.buf;
music->cvt.buf = music->resample.buf;
SDL_ConvertAudio(&music->cvt);
music->resample.buf_len = music->cvt.len_cvt;
music->cvt.buf = orig;
}
continue;
} else {
Uint8 *data;
if ((stop - pos) < len) {
len = (int)(stop - pos);
}
data = SDL_stack_alloc(Uint8, len);
if (data) {
len = SDL_RWread(music->src, data, 1, len);
SDL_MixAudio(stream, data, len, wavestream_volume);
SDL_stack_free(data);
}
consumed = len;
bytes_remaining = 0;
}
if ((stop - pos) < original_len) {
original_len = (int)(stop - pos);
}
original_len = SDL_RWread(music->src, music->cvt.buf, 1, original_len);
/* At least at the time of writing, SDL_ConvertAudio()
does byte-order swapping starting at the end of the
buffer. Thus, if we are reading 16-bit samples, we
had better make damn sure that we get an even
number of bytes, or we'll get garbage.
*/
if ((music->cvt.src_format & 0x0010) && (original_len & 1)) {
original_len--;
}
music->cvt.len = original_len;
SDL_ConvertAudio(&music->cvt);
SDL_MixAudio(stream, music->cvt.buf, music->cvt.len_cvt, wavestream_volume);
consumed = music->cvt.len_cvt;
} else {
Uint8 *data;
if ((stop - pos) < len) {
len = (int)(stop - pos);
}
data = SDL_stack_alloc(Uint8, len);
if (data) {
len = SDL_RWread(music->src, data, 1, len);
SDL_MixAudio(stream, data, len, wavestream_volume);
SDL_stack_free(data);
}
consumed = len;
}

if (loop && SDL_RWtell(music->src) >= stop) {
@@ -265,6 +340,7 @@ static int PlaySome(Uint8 *stream, int len)
--loop->current_play_count;
}
SDL_RWseek(music->src, loop_start, RW_SEEK_SET);
music->resample.buf_len = 0;
}
}
return consumed;
@@ -23,6 +23,8 @@

/* This file supports streaming WAV files */

#include "resample/my_resample.h"

typedef struct {
SDL_bool active;
Uint32 start;
@@ -40,6 +42,7 @@ typedef struct {
SDL_AudioCVT cvt;
int numloops;
WAVLoopPoint *loops;
struct MyResampler resample;
} WAVStream;

/* Initialize the WAVStream player, with the given mixer settings