gosu 1.4.1 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/dependencies/SDL_sound/SDL_sound.c +21 -63
- data/dependencies/SDL_sound/SDL_sound.h +2 -2
- data/dependencies/SDL_sound/SDL_sound_aiff.c +26 -23
- data/dependencies/SDL_sound/SDL_sound_au.c +8 -8
- data/dependencies/SDL_sound/SDL_sound_coreaudio.c +4 -5
- data/dependencies/SDL_sound/SDL_sound_flac.c +28 -30
- data/dependencies/SDL_sound/SDL_sound_internal.h +4 -4
- data/dependencies/SDL_sound/SDL_sound_modplug.c +1 -1
- data/dependencies/SDL_sound/SDL_sound_mp3.c +19 -23
- data/dependencies/SDL_sound/SDL_sound_raw.c +5 -6
- data/dependencies/SDL_sound/SDL_sound_shn.c +4 -4
- data/dependencies/SDL_sound/SDL_sound_voc.c +15 -15
- data/dependencies/SDL_sound/SDL_sound_vorbis.c +14 -7
- data/dependencies/SDL_sound/SDL_sound_wav.c +17 -17
- data/dependencies/SDL_sound/dr_flac.h +10840 -4779
- data/dependencies/SDL_sound/dr_mp3.h +2793 -1004
- data/dependencies/SDL_sound/libmodplug/fastmix.c +5 -0
- data/dependencies/SDL_sound/libmodplug/load_669.c +1 -1
- data/dependencies/SDL_sound/libmodplug/load_amf.c +1 -0
- data/dependencies/SDL_sound/libmodplug/load_ams.c +38 -22
- data/dependencies/SDL_sound/libmodplug/load_it.c +18 -14
- data/dependencies/SDL_sound/libmodplug/load_mdl.c +18 -9
- data/dependencies/SDL_sound/libmodplug/load_med.c +7 -6
- data/dependencies/SDL_sound/libmodplug/load_mt2.c +36 -17
- data/dependencies/SDL_sound/libmodplug/load_okt.c +51 -24
- data/dependencies/SDL_sound/libmodplug/load_psm.c +4 -2
- data/dependencies/SDL_sound/libmodplug/load_s3m.c +4 -4
- data/dependencies/SDL_sound/libmodplug/load_ult.c +4 -3
- data/dependencies/SDL_sound/libmodplug/load_xm.c +5 -5
- data/dependencies/SDL_sound/libmodplug/snd_fx.c +8 -1
- data/dependencies/SDL_sound/libmodplug/sndfile.c +21 -4
- data/dependencies/SDL_sound/stb_vorbis.h +10 -18
- data/dependencies/mojoAL/mojoal.c +260 -6
- data/dependencies/stb/stb_image.h +208 -73
- data/dependencies/stb/stb_image_write.h +57 -23
- data/dependencies/stb/stb_truetype.h +345 -279
- data/dependencies/utf8proc/utf8proc.c +37 -18
- data/dependencies/utf8proc/utf8proc.h +17 -5
- data/dependencies/utf8proc/utf8proc_data.h +12012 -10089
- data/include/Gosu/Buttons.hpp +103 -103
- data/include/Gosu/Directories.hpp +31 -24
- data/include/Gosu/Font.hpp +4 -2
- data/include/Gosu/Gosu.hpp +5 -8
- data/include/Gosu/IO.hpp +0 -3
- data/include/Gosu/Math.hpp +0 -3
- data/include/Gosu/Timing.hpp +2 -8
- data/include/Gosu/Version.hpp +1 -1
- data/src/AudioImpl.cpp +0 -7
- data/src/AudioImpl.hpp +1 -3
- data/src/BitmapIO.cpp +23 -2
- data/src/DirectoriesApple.cpp +25 -24
- data/src/DirectoriesUnix.cpp +14 -12
- data/src/DirectoriesWin.cpp +26 -30
- data/src/Font.cpp +12 -2
- data/src/Image.cpp +10 -15
- data/src/RubyGosu.cxx +6 -34
- data/src/TimingApple.cpp +1 -7
- data/src/TimingUnix.cpp +0 -6
- data/src/TimingWin.cpp +0 -6
- data/src/Window.cpp +4 -3
- metadata +2 -2
@@ -92,6 +92,7 @@ void CSoundFile_S3MConvert(MODCOMMAND *m, BOOL bIT)
|
|
92
92
|
case 'X': command = CMD_PANNING8; break;
|
93
93
|
case 'Y': command = CMD_PANBRELLO; break;
|
94
94
|
case 'Z': command = CMD_MIDI; break;
|
95
|
+
case '\\': command = CMD_MIDI; break;
|
95
96
|
default: command = 0;
|
96
97
|
}
|
97
98
|
m->command = command;
|
@@ -165,6 +166,7 @@ BOOL CSoundFile_ReadS3M(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
|
|
165
166
|
UINT iord = psfh.ordnum;
|
166
167
|
if (iord<1) iord = 1;
|
167
168
|
if (iord > MAX_ORDERS) iord = MAX_ORDERS;
|
169
|
+
if (dwMemPos + iord + 1 >= dwMemLength) return FALSE;
|
168
170
|
if (iord)
|
169
171
|
{
|
170
172
|
if (dwMemPos + iord > dwMemLength) return FALSE;
|
@@ -185,8 +187,7 @@ BOOL CSoundFile_ReadS3M(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
|
|
185
187
|
|
186
188
|
if (nins+npat)
|
187
189
|
{
|
188
|
-
if (2*(nins+npat)
|
189
|
-
|
190
|
+
if (dwMemPos + 2*(nins+npat) >= dwMemLength) return FALSE;
|
190
191
|
SDL_memcpy(ptr, lpStream+dwMemPos, 2*(nins+npat));
|
191
192
|
dwMemPos += 2*(nins+npat);
|
192
193
|
for (UINT j = 0; j < (nins+npat); ++j) {
|
@@ -194,9 +195,8 @@ BOOL CSoundFile_ReadS3M(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
|
|
194
195
|
}
|
195
196
|
if (psfh.panning_present == 252)
|
196
197
|
{
|
197
|
-
if (dwMemPos + 32 > dwMemLength) return FALSE;
|
198
|
-
|
199
198
|
const BYTE *chnpan = lpStream+dwMemPos;
|
199
|
+
if (dwMemPos > dwMemLength - 32) return FALSE;
|
200
200
|
for (UINT i=0; i<32; i++) if (chnpan[i] & 0x20)
|
201
201
|
{
|
202
202
|
_this->ChnSettings[i].nPan = ((chnpan[i] & 0x0F) << 4) + 8;
|
@@ -128,7 +128,7 @@ BOOL CSoundFile_ReadUlt(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
|
|
128
128
|
for (UINT nPat=0; nPat<nop; nPat++)
|
129
129
|
{
|
130
130
|
MODCOMMAND *pat = NULL;
|
131
|
-
|
131
|
+
|
132
132
|
if (nPat < MAX_PATTERNS)
|
133
133
|
{
|
134
134
|
pat = _this->Patterns[nPat];
|
@@ -137,16 +137,17 @@ BOOL CSoundFile_ReadUlt(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLeng
|
|
137
137
|
UINT row = 0;
|
138
138
|
while (row < 64)
|
139
139
|
{
|
140
|
-
if (dwMemPos
|
140
|
+
if (dwMemPos > dwMemLength - 5) return TRUE;
|
141
141
|
UINT rep = 1;
|
142
142
|
UINT note = lpStream[dwMemPos++];
|
143
143
|
if (note == 0xFC)
|
144
144
|
{
|
145
|
-
if (dwMemPos + 7 > dwMemLength) return TRUE;
|
146
145
|
rep = lpStream[dwMemPos];
|
147
146
|
note = lpStream[dwMemPos+1];
|
148
147
|
dwMemPos += 2;
|
148
|
+
if (dwMemPos > dwMemLength - 4) return TRUE;
|
149
149
|
}
|
150
|
+
|
150
151
|
UINT instr = lpStream[dwMemPos++];
|
151
152
|
UINT eff = lpStream[dwMemPos++];
|
152
153
|
UINT dat1 = lpStream[dwMemPos++];
|
@@ -188,11 +188,11 @@ BOOL CSoundFile_ReadXM(CSoundFile *_this, const BYTE *lpStream, DWORD dwMemLengt
|
|
188
188
|
UINT vol = 0;
|
189
189
|
if (b & 0x80)
|
190
190
|
{
|
191
|
-
if (
|
192
|
-
if (
|
193
|
-
if (
|
194
|
-
if (
|
195
|
-
if (
|
191
|
+
if (b & 1) p->note = j < packsize ? src[j++] : 0;
|
192
|
+
if (b & 2) p->instr = j < packsize ? src[j++] : 0;
|
193
|
+
if (b & 4) vol = j < packsize ? src[j++] : 0;
|
194
|
+
if (b & 8) p->command = j < packsize ? src[j++] : 0;
|
195
|
+
if (b & 16) p->param = j < packsize ? src[j++] : 0;
|
196
196
|
} else
|
197
197
|
{
|
198
198
|
if (j + 5 > packsize) break;
|
@@ -420,7 +420,14 @@ void CSoundFile_NoteChange(CSoundFile *_this, UINT nChn, int note, BOOL bPorta,
|
|
420
420
|
if (note >= 0x80) // 0xFE or invalid note => key off
|
421
421
|
{
|
422
422
|
// Key Off
|
423
|
-
|
423
|
+
if (note < 0xFD && _this->m_nType == MOD_TYPE_IT)
|
424
|
+
{
|
425
|
+
if (_this->m_nInstruments)
|
426
|
+
pChn->dwFlags |= CHN_NOTEFADE;
|
427
|
+
} else
|
428
|
+
{
|
429
|
+
CSoundFile_KeyOff(_this, nChn);
|
430
|
+
}
|
424
431
|
// Note Cut
|
425
432
|
if (note == 0xFE)
|
426
433
|
{
|
@@ -14,8 +14,8 @@ extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
|
|
14
14
|
extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter);
|
15
15
|
extern WORD MDLReadBits(DWORD *bitbuf, UINT *bitnum, LPBYTE *ibuf, CHAR n);
|
16
16
|
extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen);
|
17
|
-
extern
|
18
|
-
extern
|
17
|
+
extern DWORD ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, DWORD channels, BOOL b215);
|
18
|
+
extern DWORD ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, DWORD channels, BOOL b215);
|
19
19
|
|
20
20
|
|
21
21
|
static void CSoundFile_UpdateSettings(CSoundFile *_this, const ModPlug_Settings *settings)
|
@@ -665,9 +665,26 @@ UINT CSoundFile_ReadSample(CSoundFile *_this, MODINSTRUMENT *pIns, UINT nFlags,
|
|
665
665
|
len = dwMemLength;
|
666
666
|
if (len < 4) break;
|
667
667
|
if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158))
|
668
|
-
ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158));
|
668
|
+
ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, 1, (nFlags == RS_IT2158));
|
669
669
|
else
|
670
|
-
ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516));
|
670
|
+
ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, 1, (nFlags == RS_IT21516));
|
671
|
+
break;
|
672
|
+
|
673
|
+
case RS_IT2148 | RSF_STEREO:
|
674
|
+
case RS_IT21416 | RSF_STEREO:
|
675
|
+
case RS_IT2158 | RSF_STEREO:
|
676
|
+
case RS_IT21516 | RSF_STEREO:
|
677
|
+
len = dwMemLength;
|
678
|
+
if (len < 4) break;
|
679
|
+
if ((nFlags == (RS_IT2148 | RSF_STEREO)) || (nFlags == (RS_IT2158 | RSF_STEREO)))
|
680
|
+
{
|
681
|
+
DWORD offset = ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, 2, (nFlags == (RS_IT2158 | RSF_STEREO)));
|
682
|
+
ITUnpack8Bit(pIns->pSample + 1, pIns->nLength, (LPBYTE)lpMemFile + offset, dwMemLength - offset, 2, (nFlags == (RS_IT2158 | RSF_STEREO)));
|
683
|
+
} else
|
684
|
+
{
|
685
|
+
DWORD offset = ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, 2, (nFlags == (RS_IT21516 | RSF_STEREO)));
|
686
|
+
ITUnpack16Bit(pIns->pSample + 2, pIns->nLength, (LPBYTE)lpMemFile + offset, dwMemLength - offset, 2, (nFlags == (RS_IT21516 | RSF_STEREO)));
|
687
|
+
}
|
671
688
|
break;
|
672
689
|
|
673
690
|
#ifndef MODPLUG_BASIC_SUPPORT
|
@@ -608,21 +608,6 @@ enum STBVorbisError
|
|
608
608
|
|
609
609
|
#include <limits.h>
|
610
610
|
|
611
|
-
/* we need alloca() regardless of STB_VORBIS_NO_CRT,
|
612
|
-
* because there is not a corresponding 'dealloca' */
|
613
|
-
#if !defined(alloca)
|
614
|
-
# if defined(HAVE_ALLOCA_H)
|
615
|
-
# include <alloca.h>
|
616
|
-
# elif defined(__GNUC__)
|
617
|
-
# define alloca __builtin_alloca
|
618
|
-
# elif defined(_MSC_VER)
|
619
|
-
# include <malloc.h>
|
620
|
-
# define alloca _alloca
|
621
|
-
# elif defined(__WATCOMC__)
|
622
|
-
# include <malloc.h>
|
623
|
-
# endif
|
624
|
-
#endif
|
625
|
-
|
626
611
|
#ifndef STB_FORCEINLINE
|
627
612
|
#if defined(_MSC_VER)
|
628
613
|
#define STB_FORCEINLINE __forceinline
|
@@ -646,7 +631,7 @@ enum STBVorbisError
|
|
646
631
|
#include <crtdbg.h>
|
647
632
|
#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1])
|
648
633
|
#else
|
649
|
-
#define CHECK(f) (
|
634
|
+
#define CHECK(f) do {} while(0)
|
650
635
|
#endif
|
651
636
|
|
652
637
|
#define MAX_BLOCKSIZE_LOG 13 // from specification
|
@@ -937,6 +922,9 @@ struct stb_vorbis
|
|
937
922
|
int channel_buffer_start;
|
938
923
|
int channel_buffer_end;
|
939
924
|
|
925
|
+
// hack: decode work buffer (used in inverse_mdct and decode_residues)
|
926
|
+
void *work_buffer;
|
927
|
+
|
940
928
|
// temporary buffers
|
941
929
|
void *temp_lengths;
|
942
930
|
void *temp_codewords;
|
@@ -971,8 +959,8 @@ static int error(vorb *f, enum STBVorbisError e)
|
|
971
959
|
|
972
960
|
#define array_size_required(count,size) (count*(sizeof(void *)+(size)))
|
973
961
|
|
974
|
-
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) :
|
975
|
-
#define temp_free(f,p) (
|
962
|
+
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : f->work_buffer)
|
963
|
+
#define temp_free(f,p) do {} while (0)
|
976
964
|
#define temp_alloc_save(f) ((f)->temp_offset)
|
977
965
|
#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
|
978
966
|
|
@@ -4297,6 +4285,9 @@ static int start_decoder(vorb *f)
|
|
4297
4285
|
// check if there's enough temp memory so we don't error later
|
4298
4286
|
if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset)
|
4299
4287
|
return error(f, VORBIS_outofmem);
|
4288
|
+
} else {
|
4289
|
+
f->work_buffer = setup_malloc(f, f->temp_memory_required);
|
4290
|
+
if (f->work_buffer == NULL) return error(f, VORBIS_outofmem);
|
4300
4291
|
}
|
4301
4292
|
|
4302
4293
|
// @TODO: stb_vorbis_seek_start expects first_audio_page_offset to point to a page
|
@@ -4376,6 +4367,7 @@ static void vorbis_deinit(stb_vorbis *p)
|
|
4376
4367
|
setup_free(p, p->bit_reverse[i]);
|
4377
4368
|
}
|
4378
4369
|
if (!p->alloc.alloc_buffer) {
|
4370
|
+
setup_free(p, p->work_buffer);
|
4379
4371
|
setup_temp_free(p, &p->temp_lengths, 0);
|
4380
4372
|
setup_temp_free(p, &p->temp_codewords, 0);
|
4381
4373
|
setup_temp_free(p, &p->temp_values, 0);
|
@@ -230,6 +230,12 @@ static int has_neon = 0;
|
|
230
230
|
#endif
|
231
231
|
#endif
|
232
232
|
|
233
|
+
/* no threads in Emscripten (at the moment...!) */
|
234
|
+
#if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)
|
235
|
+
#define init_api_lock() 1
|
236
|
+
#define grab_api_lock()
|
237
|
+
#define ungrab_api_lock()
|
238
|
+
#else
|
233
239
|
static SDL_mutex *api_lock = NULL;
|
234
240
|
|
235
241
|
static int init_api_lock(void)
|
@@ -264,6 +270,7 @@ static void ungrab_api_lock(void)
|
|
264
270
|
const int rc = SDL_UnlockMutex(api_lock);
|
265
271
|
SDL_assert(rc == 0);
|
266
272
|
}
|
273
|
+
#endif
|
267
274
|
|
268
275
|
#define ENTRYPOINT(rettype,fn,params,args) \
|
269
276
|
rettype fn params { rettype retval; grab_api_lock(); retval = _##fn args ; ungrab_api_lock(); return retval; }
|
@@ -417,6 +424,23 @@ typedef struct BufferQueue
|
|
417
424
|
SDL_atomic_t num_items; /* counts just_queued+head/tail */
|
418
425
|
} BufferQueue;
|
419
426
|
|
427
|
+
#define pitch_framesize 1024
|
428
|
+
#define pitch_framesize2 512
|
429
|
+
typedef struct PitchState
|
430
|
+
{
|
431
|
+
/* !!! FIXME: this is a wild amount of memory for pitch-shifting! */
|
432
|
+
ALfloat infifo[pitch_framesize];
|
433
|
+
ALfloat outfifo[pitch_framesize];
|
434
|
+
ALfloat workspace[2*pitch_framesize];
|
435
|
+
ALfloat lastphase[pitch_framesize2+1];
|
436
|
+
ALfloat sumphase[pitch_framesize2+1];
|
437
|
+
ALfloat outputaccum[2*pitch_framesize];
|
438
|
+
ALfloat synmagn[pitch_framesize2+1];
|
439
|
+
ALfloat synfreq[pitch_framesize2+1];
|
440
|
+
ALint rover;
|
441
|
+
} PitchState;
|
442
|
+
|
443
|
+
|
420
444
|
typedef struct ALsource ALsource;
|
421
445
|
|
422
446
|
SIMDALIGNEDSTRUCT ALsource
|
@@ -452,6 +476,7 @@ SIMDALIGNEDSTRUCT ALsource
|
|
452
476
|
ALboolean offset_latched; /* AL_SEC_OFFSET, etc, say set values apply to next alSourcePlay if not currently playing! */
|
453
477
|
ALint queue_channels;
|
454
478
|
ALsizei queue_frequency;
|
479
|
+
PitchState *pitchstate;
|
455
480
|
ALsource *playlist_next; /* linked list that contains currently-playing sources! Only touched by mixer thread! */
|
456
481
|
};
|
457
482
|
|
@@ -1124,8 +1149,222 @@ static void mix_float32_c2_neon(const ALfloat * restrict panning, const float *
|
|
1124
1149
|
#endif
|
1125
1150
|
|
1126
1151
|
|
1127
|
-
|
1152
|
+
/****************************************************************************
|
1153
|
+
*
|
1154
|
+
* pitch_fft and pitch_shift are modified versions of code from:
|
1155
|
+
*
|
1156
|
+
* http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
|
1157
|
+
*
|
1158
|
+
* The original code has this copyright/license:
|
1159
|
+
*
|
1160
|
+
*****************************************************************************
|
1161
|
+
*
|
1162
|
+
* COPYRIGHT 1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
|
1163
|
+
*
|
1164
|
+
* The Wide Open License (WOL)
|
1165
|
+
*
|
1166
|
+
* Permission to use, copy, modify, distribute and sell this software and its
|
1167
|
+
* documentation for any purpose is hereby granted without fee, provided that
|
1168
|
+
* the above copyright notice and this license appear in all source copies.
|
1169
|
+
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
|
1170
|
+
* ANY KIND. See http://www.dspguru.com/wol.htm for more information.
|
1171
|
+
*
|
1172
|
+
*****************************************************************************/
|
1173
|
+
|
1174
|
+
/* FFT routine, (C)1996 S.M.Bernsee. */
|
1175
|
+
static void pitch_fft(float *fftBuffer, int fftFrameSize, int sign)
|
1176
|
+
{
|
1177
|
+
float wr, wi, arg, *p1, *p2, temp;
|
1178
|
+
float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i;
|
1179
|
+
int i, bitm, j, le, le2, k;
|
1180
|
+
|
1181
|
+
for (i = 2; i < 2*fftFrameSize-2; i += 2) {
|
1182
|
+
for (bitm = 2, j = 0; bitm < 2*fftFrameSize; bitm <<= 1) {
|
1183
|
+
if (i & bitm) j++;
|
1184
|
+
j <<= 1;
|
1185
|
+
}
|
1186
|
+
if (i < j) {
|
1187
|
+
p1 = fftBuffer+i; p2 = fftBuffer+j;
|
1188
|
+
temp = *p1; *(p1++) = *p2;
|
1189
|
+
*(p2++) = temp; temp = *p1;
|
1190
|
+
*p1 = *p2; *p2 = temp;
|
1191
|
+
}
|
1192
|
+
}
|
1193
|
+
const int endval = (int)(SDL_log(fftFrameSize)/SDL_log(2.)+.5); /* !!! FIXME: precalc this. */
|
1194
|
+
for (k = 0, le = 2; k < endval; k++) {
|
1195
|
+
le <<= 1;
|
1196
|
+
le2 = le>>1;
|
1197
|
+
ur = 1.0;
|
1198
|
+
ui = 0.0;
|
1199
|
+
arg = M_PI / (le2>>1);
|
1200
|
+
wr = SDL_cos(arg);
|
1201
|
+
wi = sign*SDL_sin(arg);
|
1202
|
+
for (j = 0; j < le2; j += 2) {
|
1203
|
+
p1r = fftBuffer+j; p1i = p1r+1;
|
1204
|
+
p2r = p1r+le2; p2i = p2r+1;
|
1205
|
+
for (i = j; i < 2*fftFrameSize; i += le) {
|
1206
|
+
tr = *p2r * ur - *p2i * ui;
|
1207
|
+
ti = *p2r * ui + *p2i * ur;
|
1208
|
+
*p2r = *p1r - tr; *p2i = *p1i - ti;
|
1209
|
+
*p1r += tr; *p1i += ti;
|
1210
|
+
p1r += le; p1i += le;
|
1211
|
+
p2r += le; p2i += le;
|
1212
|
+
}
|
1213
|
+
tr = ur*wr - ui*wi;
|
1214
|
+
ui = ur*wi + ui*wr;
|
1215
|
+
ur = tr;
|
1216
|
+
}
|
1217
|
+
}
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
static void pitch_shift(ALsource *src, const ALbuffer *buffer, int numSampsToProcess, const float *indata, float *outdata)
|
1128
1221
|
{
|
1222
|
+
const float pitchShift = src->pitch;
|
1223
|
+
const float sampleRate = (float) buffer->frequency;
|
1224
|
+
const int osamp = 4;
|
1225
|
+
const int stepSize = pitch_framesize / osamp;
|
1226
|
+
const int inFifoLatency = pitch_framesize - stepSize;
|
1227
|
+
const double freqPerBin = sampleRate / (double)pitch_framesize;
|
1228
|
+
const double expct = 2.0 * M_PI * ((double)stepSize / (double)pitch_framesize);
|
1229
|
+
|
1230
|
+
double magn, phase, tmp, window, real, imag;
|
1231
|
+
int i,k, qpd, index;
|
1232
|
+
PitchState *state = src->pitchstate;
|
1233
|
+
|
1234
|
+
SDL_assert(state != NULL);
|
1235
|
+
|
1236
|
+
if (state->rover == 0) state->rover = inFifoLatency;
|
1237
|
+
|
1238
|
+
/* main processing loop */
|
1239
|
+
for (i = 0; i < numSampsToProcess; i++){
|
1240
|
+
|
1241
|
+
/* As long as we have not yet collected enough data just read in */
|
1242
|
+
state->infifo[state->rover] = indata[i];
|
1243
|
+
outdata[i] = state->outfifo[state->rover-inFifoLatency];
|
1244
|
+
state->rover++;
|
1245
|
+
|
1246
|
+
/* now we have enough data for processing */
|
1247
|
+
if (state->rover >= pitch_framesize) {
|
1248
|
+
state->rover = inFifoLatency;
|
1249
|
+
|
1250
|
+
/* do windowing and re,im interleave */
|
1251
|
+
for (k = 0; k < pitch_framesize;k++) {
|
1252
|
+
window = -.5*SDL_cos(2.*M_PI*(double)k/(double)pitch_framesize)+.5;
|
1253
|
+
state->workspace[2*k] = state->infifo[k] * window;
|
1254
|
+
state->workspace[2*k+1] = 0.;
|
1255
|
+
}
|
1256
|
+
|
1257
|
+
|
1258
|
+
/* ***************** ANALYSIS ******************* */
|
1259
|
+
/* do transform */
|
1260
|
+
pitch_fft(state->workspace, pitch_framesize, -1);
|
1261
|
+
|
1262
|
+
/* this is the analysis step */
|
1263
|
+
for (k = 0; k <= pitch_framesize2; k++) {
|
1264
|
+
|
1265
|
+
/* de-interlace FFT buffer */
|
1266
|
+
real = state->workspace[2*k];
|
1267
|
+
imag = state->workspace[2*k+1];
|
1268
|
+
|
1269
|
+
/* compute magnitude and phase */
|
1270
|
+
magn = 2.*SDL_sqrt(real*real + imag*imag);
|
1271
|
+
phase = SDL_atan2(imag,real);
|
1272
|
+
|
1273
|
+
/* compute phase difference */
|
1274
|
+
tmp = phase - state->lastphase[k];
|
1275
|
+
state->lastphase[k] = phase;
|
1276
|
+
|
1277
|
+
/* subtract expected phase difference */
|
1278
|
+
tmp -= (double)k*expct;
|
1279
|
+
|
1280
|
+
/* map delta phase into +/- Pi interval */
|
1281
|
+
qpd = tmp/M_PI;
|
1282
|
+
if (qpd >= 0) qpd += qpd&1;
|
1283
|
+
else qpd -= qpd&1;
|
1284
|
+
tmp -= M_PI*(double)qpd;
|
1285
|
+
|
1286
|
+
/* get deviation from bin frequency from the +/- Pi interval */
|
1287
|
+
tmp = osamp*tmp/(2.*M_PI);
|
1288
|
+
|
1289
|
+
/* compute the k-th partials' true frequency */
|
1290
|
+
tmp = (double)k*freqPerBin + tmp*freqPerBin;
|
1291
|
+
|
1292
|
+
/* store magnitude and true frequency in analysis arrays */
|
1293
|
+
state->workspace[2*k] = magn;
|
1294
|
+
state->workspace[2*k+1] = tmp;
|
1295
|
+
|
1296
|
+
}
|
1297
|
+
|
1298
|
+
/* ***************** PROCESSING ******************* */
|
1299
|
+
/* this does the actual pitch shifting */
|
1300
|
+
SDL_memset(state->synmagn, '\0', sizeof (state->synmagn));
|
1301
|
+
for (k = 0; k <= pitch_framesize2; k++) {
|
1302
|
+
index = k*pitchShift;
|
1303
|
+
if (index <= pitch_framesize2) {
|
1304
|
+
state->synmagn[index] += state->workspace[2*k];
|
1305
|
+
state->synfreq[index] = state->workspace[2*k+1] * pitchShift;
|
1306
|
+
}
|
1307
|
+
}
|
1308
|
+
|
1309
|
+
/* ***************** SYNTHESIS ******************* */
|
1310
|
+
/* this is the synthesis step */
|
1311
|
+
for (k = 0; k <= pitch_framesize2; k++) {
|
1312
|
+
|
1313
|
+
/* get magnitude and true frequency from synthesis arrays */
|
1314
|
+
magn = state->synmagn[k];
|
1315
|
+
tmp = state->synfreq[k];
|
1316
|
+
|
1317
|
+
/* subtract bin mid frequency */
|
1318
|
+
tmp -= (double)k*freqPerBin;
|
1319
|
+
|
1320
|
+
/* get bin deviation from freq deviation */
|
1321
|
+
tmp /= freqPerBin;
|
1322
|
+
|
1323
|
+
/* take osamp into account */
|
1324
|
+
tmp = 2.*M_PI*tmp/osamp;
|
1325
|
+
|
1326
|
+
/* add the overlap phase advance back in */
|
1327
|
+
tmp += (double)k*expct;
|
1328
|
+
|
1329
|
+
/* accumulate delta phase to get bin phase */
|
1330
|
+
state->sumphase[k] += tmp;
|
1331
|
+
phase = state->sumphase[k];
|
1332
|
+
|
1333
|
+
/* get real and imag part and re-interleave */
|
1334
|
+
state->workspace[2*k] = magn*SDL_cos(phase);
|
1335
|
+
state->workspace[2*k+1] = magn*SDL_sin(phase);
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
/* zero negative frequencies */
|
1339
|
+
for (k = pitch_framesize+2; k < 2*pitch_framesize; k++) state->workspace[k] = 0.;
|
1340
|
+
|
1341
|
+
/* do inverse transform */
|
1342
|
+
pitch_fft(state->workspace, pitch_framesize, 1);
|
1343
|
+
|
1344
|
+
/* do windowing and add to output accumulator */
|
1345
|
+
for(k=0; k < pitch_framesize; k++) {
|
1346
|
+
window = -.5*SDL_cos(2.*M_PI*(double)k/(double)pitch_framesize)+.5;
|
1347
|
+
state->outputaccum[k] += 2.*window*state->workspace[2*k]/(pitch_framesize2*osamp);
|
1348
|
+
}
|
1349
|
+
for (k = 0; k < stepSize; k++) state->outfifo[k] = state->outputaccum[k];
|
1350
|
+
|
1351
|
+
/* shift accumulator */
|
1352
|
+
SDL_memmove(state->outputaccum, state->outputaccum+stepSize, pitch_framesize*sizeof(float));
|
1353
|
+
|
1354
|
+
/* move input FIFO */
|
1355
|
+
for (k = 0; k < inFifoLatency; k++) state->infifo[k] = state->infifo[k+stepSize];
|
1356
|
+
}
|
1357
|
+
}
|
1358
|
+
}
|
1359
|
+
|
1360
|
+
static void mix_buffer(ALsource *src, const ALbuffer *buffer, const ALfloat * restrict panning, const float * restrict data, float * restrict stream, const ALsizei mixframes)
|
1361
|
+
{
|
1362
|
+
if ((src->pitch != 1.0f) && (src->pitchstate != NULL)) {
|
1363
|
+
float *pitched = (float *) alloca(mixframes * buffer->channels * sizeof (float));
|
1364
|
+
pitch_shift(src, buffer, mixframes * buffer->channels, data, pitched);
|
1365
|
+
data = pitched;
|
1366
|
+
}
|
1367
|
+
|
1129
1368
|
const ALfloat left = panning[0];
|
1130
1369
|
const ALfloat right = panning[1];
|
1131
1370
|
FIXME("currently expects output to be stereo");
|
@@ -1194,7 +1433,7 @@ static ALboolean mix_source_buffer(ALCcontext *ctx, ALsource *src, BufferQueueIt
|
|
1194
1433
|
const int mixbufframes = mixbuflen / bufferframesize;
|
1195
1434
|
const int getframes = SDL_min(remainingmixframes, mixbufframes);
|
1196
1435
|
SDL_AudioStreamGet(src->stream, mixbuf, getframes * bufferframesize);
|
1197
|
-
mix_buffer(buffer, src->panning, mixbuf, *stream, getframes);
|
1436
|
+
mix_buffer(src, buffer, src->panning, mixbuf, *stream, getframes);
|
1198
1437
|
*len -= getframes * deviceframesize;
|
1199
1438
|
*stream += getframes * ctx->device->channels;
|
1200
1439
|
remainingmixframes -= getframes;
|
@@ -1202,7 +1441,7 @@ static ALboolean mix_source_buffer(ALCcontext *ctx, ALsource *src, BufferQueueIt
|
|
1202
1441
|
} else {
|
1203
1442
|
const int framesavail = (buffer->len - src->offset) / bufferframesize;
|
1204
1443
|
const int mixframes = SDL_min(framesneeded, framesavail);
|
1205
|
-
mix_buffer(buffer, src->panning, data, *stream, mixframes);
|
1444
|
+
mix_buffer(src, buffer, src->panning, data, *stream, mixframes);
|
1206
1445
|
src->offset += mixframes * bufferframesize;
|
1207
1446
|
*len -= mixframes * deviceframesize;
|
1208
1447
|
*stream += mixframes * ctx->device->channels;
|
@@ -3433,6 +3672,19 @@ static ALboolean _alIsSource(const ALuint name)
|
|
3433
3672
|
}
|
3434
3673
|
ENTRYPOINT(ALboolean,alIsSource,(ALuint name),(name))
|
3435
3674
|
|
3675
|
+
static void source_set_pitch(ALCcontext *ctx, ALsource *src, const ALfloat pitch)
|
3676
|
+
{
|
3677
|
+
/* only allocate pitchstate if the pitch every changes, because it's a lot of
|
3678
|
+
RAM and we leave it allocated to the source until forever once needed */
|
3679
|
+
if ((pitch != 1.0f) && (src->pitchstate == NULL)) {
|
3680
|
+
src->pitchstate = (PitchState *) SDL_calloc(1, sizeof (PitchState));
|
3681
|
+
if (src->pitchstate == NULL) {
|
3682
|
+
set_al_error(ctx, AL_OUT_OF_MEMORY);
|
3683
|
+
}
|
3684
|
+
}
|
3685
|
+
src->pitch = pitch;
|
3686
|
+
}
|
3687
|
+
|
3436
3688
|
static void _alSourcefv(const ALuint name, const ALenum param, const ALfloat *values)
|
3437
3689
|
{
|
3438
3690
|
ALCcontext *ctx = get_current_context();
|
@@ -3449,7 +3701,7 @@ static void _alSourcefv(const ALuint name, const ALenum param, const ALfloat *va
|
|
3449
3701
|
case AL_REFERENCE_DISTANCE: src->reference_distance = *values; break;
|
3450
3702
|
case AL_ROLLOFF_FACTOR: src->rolloff_factor = *values; break;
|
3451
3703
|
case AL_MAX_DISTANCE: src->max_distance = *values; break;
|
3452
|
-
case AL_PITCH: src
|
3704
|
+
case AL_PITCH: source_set_pitch(ctx, src, *values); break;
|
3453
3705
|
case AL_CONE_INNER_ANGLE: src->cone_inner_angle = *values; break;
|
3454
3706
|
case AL_CONE_OUTER_ANGLE: src->cone_outer_angle = *values; break;
|
3455
3707
|
case AL_CONE_OUTER_GAIN: src->cone_outer_gain = *values; break;
|
@@ -3654,7 +3906,7 @@ static void _alGetSourcefv(const ALuint name, const ALenum param, ALfloat *value
|
|
3654
3906
|
case AL_REFERENCE_DISTANCE: *values = src->reference_distance; break;
|
3655
3907
|
case AL_ROLLOFF_FACTOR: *values = src->rolloff_factor; break;
|
3656
3908
|
case AL_MAX_DISTANCE: *values = src->max_distance; break;
|
3657
|
-
case AL_PITCH: *values
|
3909
|
+
case AL_PITCH: source_set_pitch(ctx, src, *values); break;
|
3658
3910
|
case AL_CONE_INNER_ANGLE: *values = src->cone_inner_angle; break;
|
3659
3911
|
case AL_CONE_OUTER_ANGLE: *values = src->cone_outer_angle; break;
|
3660
3912
|
case AL_CONE_OUTER_GAIN: *values = src->cone_outer_gain; break;
|
@@ -3955,7 +4207,7 @@ static float source_get_offset(ALsource *src, ALenum param)
|
|
3955
4207
|
int proc_buf = SDL_AtomicGet(&src->buffer_queue_processed.num_items);
|
3956
4208
|
offset = (proc_buf * item->buffer->len + src->offset);
|
3957
4209
|
}
|
3958
|
-
} else {
|
4210
|
+
} else if (src->buffer) {
|
3959
4211
|
framesize = (int) (src->buffer->channels * sizeof (float));
|
3960
4212
|
freq = (int) src->buffer->frequency;
|
3961
4213
|
offset = src->offset;
|
@@ -4482,12 +4734,14 @@ static void _alBufferData(const ALuint name, const ALenum alfmt, const ALvoid *d
|
|
4482
4734
|
if (rc == 1) { /* conversion necessary */
|
4483
4735
|
rc = SDL_ConvertAudio(&sdlcvt);
|
4484
4736
|
SDL_assert(rc == 0); /* this shouldn't fail. */
|
4737
|
+
#if 0 /* !!! FIXME: need realloc_simd_aligned. */
|
4485
4738
|
if (sdlcvt.len_cvt < (size * sdlcvt.len_mult)) { /* maybe shrink buffer */
|
4486
4739
|
void *ptr = SDL_realloc(sdlcvt.buf, sdlcvt.len_cvt);
|
4487
4740
|
if (ptr) {
|
4488
4741
|
sdlcvt.buf = (Uint8 *) ptr;
|
4489
4742
|
}
|
4490
4743
|
}
|
4744
|
+
#endif
|
4491
4745
|
}
|
4492
4746
|
|
4493
4747
|
free_simd_aligned((void *) buffer->data); /* nuke any previous data. */
|