annotate decoders/speex.c @ 531:8f93b3ff2d38

Updated TODO.
author Ryan C. Gordon <icculus@icculus.org>
date Thu, 17 Apr 2008 17:43:02 +0000
parents b5ddeebce808
children a116d8f628a0
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 *
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
37 * Please see the file COPYING in the source's root directory.
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>
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
54 #include <speex.h>
573eaefef003 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
55 #include <speex_header.h>
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