annotate decoders/speex.c @ 562:7e08477b0fc1

MP3 decoder upgrade work. Ripped out SMPEG and mpglib support, replaced it with "mpg123.c" and libmpg123. libmpg123 is a much better version of mpglib, so it should solve all the problems about MP3's not seeking, or most modern MP3's not playing at all, etc. Since you no longer have to make a tradeoff with SMPEG for features, and SMPEG is basically rotting, I removed it from the project. There is still work to be done with libmpg123...there are MMX, 3DNow, SSE, Altivec, etc decoders which we don't have enabled at the moment, and the build system could use some work to make this compile more cleanly, etc. Still: huge win.
author Ryan C. Gordon <icculus@icculus.org>
date Fri, 30 Jan 2009 02:44:47 -0500
parents 2e8907ff98e9
children a737d89af74e
rev   line source
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
1 /*
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
2 * SDL_sound -- An abstract sound format decoding API.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
3 * Copyright (C) 2001 Ryan C. Gordon.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
4 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
5 * This library is free software; you can redistribute it and/or
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
6 * modify it under the terms of the GNU Lesser General Public
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
7 * License as published by the Free Software Foundation; either
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
8 * version 2.1 of the License, or (at your option) any later version.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
9 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
10 * This library is distributed in the hope that it will be useful,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
13 * Lesser General Public License for more details.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
14 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
15 * You should have received a copy of the GNU Lesser General Public
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
16 * License along with this library; if not, write to the Free Software
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
18 */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
19
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
20 /*
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
21 * Speex decoder for SDL_sound.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
22 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
23 * This driver handles Speex audio data. Speex is a codec for speech that is
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
24 * meant to be transmitted over narrowband network connections. Epic Games
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
25 * estimates that their VoIP solution, built on top of Speex, uses around
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
26 * 500 bytes per second or less to transmit relatively good sounding speech.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
27 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
28 * This decoder processes the .spx files that the speexenc program produces.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
29 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
30 * Speex isn't meant for general audio compression. Something like Ogg Vorbis
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
31 * will give better results in that case.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
32 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
33 * Further Speex information can be found at http://www.speex.org/
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
34 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
35 * This code is based on speexdec.c (see the Speex website).
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
36 *
552
2e8907ff98e9 Replaced references to COPYING with references to LICENSE.txt ...
Ryan C. Gordon <icculus@icculus.org>
parents: 534
diff changeset
37 * Please see the file LICENSE.txt in the source's root directory.
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
38 *
526
2df1f5c62d38 Updated my email address.
Ryan C. Gordon <icculus@icculus.org>
parents: 510
diff changeset
39 * This file written by Ryan C. Gordon. (icculus@icculus.org)
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
40 */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
41
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
42 #if HAVE_CONFIG_H
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
43 # include <config.h>
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
44 #endif
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
45
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
46 #ifdef SOUND_SUPPORTS_SPEEX
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
47
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
48 #include <stdio.h>
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
49 #include <stdlib.h>
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
50 #include <string.h>
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
51 #include <assert.h>
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
52
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
53 #include <ogg/ogg.h>
534
a116d8f628a0 Merged r541:543 from branches/stable-1.0: Speex include directory fix.
Ryan C. Gordon <icculus@icculus.org>
parents: 527
diff changeset
54 #include <speex/speex.h>
a116d8f628a0 Merged r541:543 from branches/stable-1.0: Speex include directory fix.
Ryan C. Gordon <icculus@icculus.org>
parents: 527
diff changeset
55 #include <speex/speex_header.h>
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
56
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
57 #include "SDL_sound.h"
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
58
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
59 #define __SDL_SOUND_INTERNAL__
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
60 #include "SDL_sound_internal.h"
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
61
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
62 static int SPEEX_init(void);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
63 static void SPEEX_quit(void);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
64 static int SPEEX_open(Sound_Sample *sample, const char *ext);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
65 static void SPEEX_close(Sound_Sample *sample);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
66 static Uint32 SPEEX_read(Sound_Sample *sample);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
67 static int SPEEX_rewind(Sound_Sample *sample);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
68 static int SPEEX_seek(Sound_Sample *sample, Uint32 ms);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
69
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
70 static const char *extensions_speex[] = { "spx", NULL };
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
71 const Sound_DecoderFunctions __Sound_DecoderFunctions_SPEEX =
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
72 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
73 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
74 extensions_speex,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
75 "SPEEX speech compression format",
526
2df1f5c62d38 Updated my email address.
Ryan C. Gordon <icculus@icculus.org>
parents: 510
diff changeset
76 "Ryan C. Gordon <icculus@icculus.org>",
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
77 "http://www.icculus.org/SDL_sound/"
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
78 },
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
79
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
80 SPEEX_init, /* init() method */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
81 SPEEX_quit, /* quit() method */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
82 SPEEX_open, /* open() method */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
83 SPEEX_close, /* close() method */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
84 SPEEX_read, /* read() method */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
85 SPEEX_rewind, /* rewind() method */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
86 SPEEX_seek /* seek() method */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
87 };
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
88
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
89 #define SPEEX_USE_PERCEPTUAL_ENHANCER 1
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
90 #define SPEEX_MAGIC 0x5367674F /* "OggS" in ASCII (littleendian) */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
91 #define SPEEX_OGG_BUFSIZE 200
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
92
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
93 /* this is what we store in our internal->decoder_private field... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
94 typedef struct
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
95 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
96 ogg_sync_state oy;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
97 ogg_page og;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
98 ogg_packet op;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
99 ogg_stream_state os;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
100 void *state;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
101 SpeexBits bits;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
102 int header_count;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
103 int frame_size;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
104 int nframes;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
105 int frames_avail;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
106 float *decode_buf;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
107 int decode_total;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
108 int decode_pos;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
109 int have_ogg_packet;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
110 } speex_t;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
111
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
112
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
113 static int SPEEX_init(void)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
114 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
115 return(1); /* no-op. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
116 } /* SPEEX_init */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
117
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
118
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
119 static void SPEEX_quit(void)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
120 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
121 /* no-op. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
122 } /* SPEEX_quit */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
123
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
124
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
125 static int process_header(speex_t *speex, Sound_Sample *sample)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
126 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
127 SpeexMode *mode;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
128 SpeexHeader *hptr;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
129 SpeexHeader header;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
130 int enh_enabled = SPEEX_USE_PERCEPTUAL_ENHANCER;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
131 int tmp;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
132
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
133 hptr = speex_packet_to_header((char*) speex->op.packet, speex->op.bytes);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
134 BAIL_IF_MACRO(!hptr, "SPEEX: Cannot read header", 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
135 memcpy(&header, hptr, sizeof (SpeexHeader)); /* move to stack. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
136 free(hptr); /* lame that this forces you to malloc... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
137
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
138 BAIL_IF_MACRO(header.mode >= SPEEX_NB_MODES, "SPEEX: Unknown mode", 0);
527
b5ddeebce808 Check if Speex header has bogus data (CVE-2008-1686).
Ryan C. Gordon <icculus@icculus.org>
parents: 526
diff changeset
139 BAIL_IF_MACRO(header.mode < 0, "SPEEX: Unknown mode", 0);
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
140 mode = speex_mode_list[header.mode];
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
141 BAIL_IF_MACRO(header.speex_version_id > 1, "SPEEX: Unknown version", 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
142 BAIL_IF_MACRO(mode->bitstream_version < header.mode_bitstream_version,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
143 "SPEEX: Unsupported bitstream version", 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
144 BAIL_IF_MACRO(mode->bitstream_version > header.mode_bitstream_version,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
145 "SPEEX: Unsupported bitstream version", 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
146
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
147 speex->state = speex_decoder_init(mode);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
148 BAIL_IF_MACRO(!speex->state, "SPEEX: Decoder initialization error", 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
149
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
150 speex_decoder_ctl(speex->state, SPEEX_SET_ENH, &enh_enabled);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
151 speex_decoder_ctl(speex->state, SPEEX_GET_FRAME_SIZE, &speex->frame_size);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
152
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
153 speex->decode_buf = (float *) malloc(speex->frame_size * sizeof (float));
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
154 BAIL_IF_MACRO(!speex->decode_buf, ERR_OUT_OF_MEMORY, 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
155
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
156 speex->nframes = header.frames_per_packet;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
157 if (!speex->nframes)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
158 speex->nframes = 1;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
159
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
160 /* !!! FIXME: Write converters to match desired format.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
161 !!! FIXME: We have to convert from Float32 anyhow. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
162 /* !!! FIXME: Is it a performance hit to alter sampling rate?
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
163 !!! FIXME: If not, try to match desired rate. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
164 /* !!! FIXME: We force mono output, but speexdec.c has code for stereo.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
165 !!! FIXME: Use that if sample->desired.channels == 2? */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
166 tmp = header.rate;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
167 speex_decoder_ctl(speex->state, SPEEX_SET_SAMPLING_RATE, &tmp);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
168 speex_decoder_ctl(speex->state, SPEEX_GET_SAMPLING_RATE, &tmp);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
169 sample->actual.rate = tmp;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
170 sample->actual.channels = 1;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
171 sample->actual.format = AUDIO_S16SYS;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
172
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
173 SNDDBG(("SPEEX: %dHz, mono, %svbr, %s mode.\n",
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
174 (int) sample->actual.rate,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
175 header.vbr ? "" : "not ",
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
176 mode->modeName));
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
177
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
178 /* plus 2: one for this header, one for the comment header. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
179 speex->header_count = header.extra_headers + 2;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
180 return(1);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
181 } /* process_header */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
182
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
183
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
184 /* !!! FIXME: this code sucks. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
185 static int SPEEX_open(Sound_Sample *sample, const char *ext)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
186 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
187 int set_error_str = 1;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
188 int bitstream_initialized = 0;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
189 Uint8 *buffer = NULL;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
190 int packet_count = 0;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
191 speex_t *speex = NULL;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
192 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
193 SDL_RWops *rw = internal->rw;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
194 Uint32 magic;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
195
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
196 /* Quick rejection. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
197 /*
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
198 * !!! FIXME: If (ext) is .spx, ignore bad magic number and assume
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
199 * !!! FIXME: this is a corrupted file...try to sync up further in
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
200 * !!! FIXME: stream. But for general purposes we can't read the
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
201 * !!! FIXME: whole RWops here in case it's not a Speex file at all.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
202 */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
203 magic = SDL_ReadLE32(rw); /* make sure this is an ogg stream. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
204 BAIL_IF_MACRO(magic != SPEEX_MAGIC, "SPEEX: Not a complete ogg stream", 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
205 BAIL_IF_MACRO(SDL_RWseek(rw, -4, SEEK_CUR) < 0, ERR_IO_ERROR, 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
206
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
207 speex = (speex_t *) malloc(sizeof (speex_t));
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
208 BAIL_IF_MACRO(speex == NULL, ERR_OUT_OF_MEMORY, 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
209 memset(speex, '\0', sizeof (speex_t));
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
210
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
211 speex_bits_init(&speex->bits);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
212 if (ogg_sync_init(&speex->oy) != 0) goto speex_open_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
213
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
214 while (1)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
215 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
216 int rc;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
217 Uint8 *buffer = (Uint8*)ogg_sync_buffer(&speex->oy, SPEEX_OGG_BUFSIZE);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
218 if (buffer == NULL) goto speex_open_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
219 rc = SDL_RWread(rw, buffer, 1, SPEEX_OGG_BUFSIZE);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
220 if (rc <= 0) goto speex_open_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
221 if (ogg_sync_wrote(&speex->oy, rc) != 0) goto speex_open_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
222 while (ogg_sync_pageout(&speex->oy, &speex->og) == 1)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
223 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
224 if (!bitstream_initialized)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
225 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
226 if (ogg_stream_init(&speex->os, ogg_page_serialno(&speex->og)))
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
227 goto speex_open_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
228 bitstream_initialized = 1;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
229 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
230
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
231 if (ogg_stream_pagein(&speex->os, &speex->og) != 0)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
232 goto speex_open_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
233
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
234 while (ogg_stream_packetout(&speex->os, &speex->op) == 1)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
235 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
236 if (speex->op.e_o_s)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
237 goto speex_open_failed; /* end of stream already?! */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
238
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
239 packet_count++;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
240 if (packet_count == 1) /* need speex header. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
241 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
242 if (!process_header(speex, sample))
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
243 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
244 set_error_str = 0; /* process_header will set error string. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
245 goto speex_open_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
246 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
247 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
248
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
249 if (packet_count > speex->header_count)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
250 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
251 /* if you made it here, you're ready to get a waveform. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
252 SNDDBG(("SPEEX: Accepting data stream.\n"));
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
253
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
254 /* sample->actual is configured in process_header()... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
255 speex->have_ogg_packet = 1;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
256 sample->flags = SOUND_SAMPLEFLAG_NONE;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
257 internal->decoder_private = speex;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
258 return(1); /* we'll handle this data. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
259 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
260 } /* while */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
261
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
262 } /* while */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
263
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
264 } /* while */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
265
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
266 assert(0); /* shouldn't hit this point. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
267
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
268 speex_open_failed:
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
269 if (speex != NULL)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
270 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
271 if (speex->state != NULL)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
272 speex_decoder_destroy(speex->state);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
273 if (bitstream_initialized)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
274 ogg_stream_clear(&speex->os);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
275 speex_bits_destroy(&speex->bits);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
276 ogg_sync_clear(&speex->oy);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
277 free(speex->decode_buf);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
278 free(speex);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
279 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
280
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
281 if (set_error_str)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
282 BAIL_MACRO("SPEEX: decoding error", 0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
283
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
284 return(0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
285 } /* SPEEX_open */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
286
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
287
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
288 static void SPEEX_close(Sound_Sample *sample)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
289 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
290 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
291 speex_t *speex = (speex_t *) internal->decoder_private;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
292 speex_decoder_destroy(speex->state);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
293 ogg_stream_clear(&speex->os);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
294 speex_bits_destroy(&speex->bits);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
295 ogg_sync_clear(&speex->oy);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
296 free(speex->decode_buf);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
297 free(speex);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
298 } /* SPEEX_close */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
299
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
300
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
301 static Uint32 copy_from_decoded(speex_t *speex,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
302 Sound_SampleInternal *internal,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
303 Uint32 _cpypos)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
304 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
305 /*
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
306 * !!! FIXME: Obviously, this all needs to change if we allow for
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
307 * !!! FIXME: more than mono, S16SYS data.
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
308 */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
309 Uint32 cpypos = _cpypos >> 1;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
310 Sint16 *dst = ((Sint16 *) internal->buffer) + cpypos;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
311 Sint16 *max;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
312 Uint32 maxoutput = (internal->buffer_size >> 1) - cpypos;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
313 Uint32 maxavail = speex->decode_total - speex->decode_pos;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
314 float *src = speex->decode_buf + speex->decode_pos;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
315
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
316 if (maxavail < maxoutput)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
317 maxoutput = maxavail;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
318
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
319 speex->decode_pos += maxoutput;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
320 cpypos += maxoutput;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
321
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
322 for (max = dst + maxoutput; dst < max; dst++, src++)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
323 {
454
6bd7ca7d218b Took out a C++-style comment.
Ryan C. Gordon <icculus@icculus.org>
parents: 451
diff changeset
324 /* !!! FIXME: This screams for vectorization. */
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
325 register float f = *src;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
326 if (f > 32000.0f) /* eh, speexdec.c clamps like this, too. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
327 f = 32000.0f;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
328 else if (f < -32000.0f)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
329 f = -32000.0f;
454
6bd7ca7d218b Took out a C++-style comment.
Ryan C. Gordon <icculus@icculus.org>
parents: 451
diff changeset
330 *dst = (Sint16) (0.5f + f);
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
331 } /* for */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
332
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
333 return(cpypos << 1);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
334 } /* copy_from_decoded */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
335
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
336
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
337 /* !!! FIXME: this code sucks. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
338 static Uint32 SPEEX_read(Sound_Sample *sample)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
339 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
340 Uint32 retval = 0;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
341 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
342 speex_t *speex = (speex_t *) internal->decoder_private;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
343 SDL_RWops *rw = internal->rw;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
344 Uint8 *buffer;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
345 int rc;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
346
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
347 while (1)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
348 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
349 /* see if there's some already-decoded leftovers... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
350 if (speex->decode_total != speex->decode_pos)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
351 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
352 retval = copy_from_decoded(speex, internal, retval);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
353 if (retval >= internal->buffer_size)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
354 return(retval); /* whee. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
355 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
356
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
357 /* okay, decoded buffer is spent. What else do we have? */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
358 speex->decode_total = speex->decode_pos = 0;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
359
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
360 if (speex->frames_avail) /* have more frames to decode? */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
361 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
362 rc = speex_decode(speex->state, &speex->bits, speex->decode_buf);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
363 if (rc < 0) goto speex_read_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
364 if (speex_bits_remaining(&speex->bits) < 0) goto speex_read_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
365 speex->frames_avail--;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
366 speex->decode_total = speex->frame_size;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
367 continue; /* go fill the output buffer... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
368 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
369
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
370 /* need to get more speex frames from available ogg packets... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
371 if (speex->have_ogg_packet)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
372 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
373 speex_bits_read_from(&speex->bits,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
374 (char *) speex->op.packet,
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
375 speex->op.bytes);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
376
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
377 speex->frames_avail += speex->nframes;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
378 if (ogg_stream_packetout(&speex->os, &speex->op) <= 0)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
379 speex->have_ogg_packet = 0;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
380 continue; /* go decode these frames. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
381 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
382
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
383 /* need to get more ogg packets from bitstream... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
384
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
385 if (speex->op.e_o_s) /* okay, we're really spent. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
386 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
387 sample->flags |= SOUND_SAMPLEFLAG_EOF;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
388 return(retval);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
389 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
390
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
391 while ((!speex->op.e_o_s) && (!speex->have_ogg_packet))
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
392 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
393 buffer = (Uint8 *) ogg_sync_buffer(&speex->oy, SPEEX_OGG_BUFSIZE);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
394 if (buffer == NULL) goto speex_read_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
395 rc = SDL_RWread(rw, buffer, 1, SPEEX_OGG_BUFSIZE);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
396 if (rc <= 0) goto speex_read_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
397 if (ogg_sync_wrote(&speex->oy, rc) != 0) goto speex_read_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
398
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
399 /* got complete ogg page? */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
400 if (ogg_sync_pageout(&speex->oy, &speex->og) == 1)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
401 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
402 if (ogg_stream_pagein(&speex->os, &speex->og) != 0)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
403 goto speex_read_failed;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
404
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
405 /* got complete ogg packet? */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
406 if (ogg_stream_packetout(&speex->os, &speex->op) == 1)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
407 speex->have_ogg_packet = 1;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
408 } /* if */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
409 } /* while */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
410 } /* while */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
411
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
412 assert(0); /* never hit this. Either return or goto speex_read_failed */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
413
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
414 speex_read_failed:
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
415 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
416 /* !!! FIXME: "i/o error" is better in some situations. */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
417 BAIL_MACRO("SPEEX: Decoding error", retval);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
418 } /* SPEEX_read */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
419
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
420
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
421 static int SPEEX_rewind(Sound_Sample *sample)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
422 {
510
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
423 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
424 /*
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
425 * !!! FIXME: This is really unacceptable; state should be reset and
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
426 * !!! FIXME: the RWops should be pointed to the start of the data
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
427 * !!! FIXME: to decode. The below kludge adds unneeded overhead and
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
428 * !!! FIXME: risk of failure.
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
429 */
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
430 BAIL_IF_MACRO(SDL_RWseek(internal->rw, 0, SEEK_SET) != 0, ERR_IO_ERROR, 0);
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
431 SPEEX_close(sample);
1841bdcf2122 Completely unacceptable hack for Speex rewinding.
Ryan C. Gordon <icculus@icculus.org>
parents: 454
diff changeset
432 return(SPEEX_open(sample, "SPX"));
451
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
433 } /* SPEEX_rewind */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
434
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
435
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
436 static int SPEEX_seek(Sound_Sample *sample, Uint32 ms)
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
437 {
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
438 /* !!! FIXME */ return(0);
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
439 } /* SPEEX_seek */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
440
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
441
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
442 #endif /* SOUND_SUPPORTS_SPEEX */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
443
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
444 /* end of speex.c ... */
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
445