Remove lots of simulator-speficic #ifdef'ing in sound.c to allow for DSP effects...
[kugel-rb.git] / uisimulator / sdl / sound.c
blobaa689b921d10688a5ad738125353ffb8a3fccb98
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 by Nick Lanham
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "autoconf.h"
24 #include <stdlib.h>
25 #include <stdbool.h>
26 #include <memory.h>
27 #include "debug.h"
28 #include "kernel.h"
29 #include "sound.h"
30 #include "audiohw.h"
32 #include "pcm.h"
33 #include "pcm_sampr.h"
34 #include "SDL.h"
36 static int sim_volume = 0;
38 #if CONFIG_CODEC == SWCODEC
39 static int cvt_status = -1;
41 static Uint8* pcm_data;
42 static size_t pcm_data_size;
43 static size_t pcm_sample_bytes;
44 static size_t pcm_channel_bytes;
46 struct pcm_udata
48 Uint8 *stream;
49 Uint32 num_in;
50 Uint32 num_out;
51 FILE *debug;
52 } udata;
54 static SDL_AudioSpec obtained;
55 static SDL_AudioCVT cvt;
57 extern bool debug_audio;
59 #ifndef MIN
60 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
61 #endif
63 void pcm_play_lock(void)
65 SDL_LockAudio();
68 void pcm_play_unlock(void)
70 SDL_UnlockAudio();
73 static void pcm_dma_apply_settings_nolock(void)
75 cvt_status = SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, 2, pcm_sampr,
76 obtained.format, obtained.channels, obtained.freq);
78 if (cvt_status < 0) {
79 cvt.len_ratio = (double)obtained.freq / (double)pcm_sampr;
83 void pcm_dma_apply_settings(void)
85 pcm_play_lock();
86 pcm_dma_apply_settings_nolock();
87 pcm_play_unlock();
90 void pcm_play_dma_start(const void *addr, size_t size)
92 pcm_dma_apply_settings_nolock();
94 pcm_data = (Uint8 *) addr;
95 pcm_data_size = size;
97 SDL_PauseAudio(0);
100 void pcm_play_dma_stop(void)
102 SDL_PauseAudio(1);
103 if (udata.debug != NULL) {
104 fclose(udata.debug);
105 udata.debug = NULL;
106 DEBUGF("Audio debug file closed\n");
110 void pcm_play_dma_pause(bool pause)
112 if (pause)
113 SDL_PauseAudio(1);
114 else
115 SDL_PauseAudio(0);
118 size_t pcm_get_bytes_waiting(void)
120 return pcm_data_size;
123 extern int sim_volume; /* in firmware/sound.c */
124 void write_to_soundcard(struct pcm_udata *udata) {
125 if (debug_audio && (udata->debug == NULL)) {
126 udata->debug = fopen("audiodebug.raw", "ab");
127 DEBUGF("Audio debug file open\n");
130 if (cvt.needed) {
131 Uint32 rd = udata->num_in;
132 Uint32 wr = (double)rd * cvt.len_ratio;
134 if (wr > udata->num_out) {
135 wr = udata->num_out;
136 rd = (double)wr / cvt.len_ratio;
138 if (rd > udata->num_in)
140 rd = udata->num_in;
141 wr = (double)rd * cvt.len_ratio;
145 if (wr == 0 || rd == 0)
147 udata->num_out = udata->num_in = 0;
148 return;
151 if (cvt_status > 0) {
152 cvt.len = rd * pcm_sample_bytes;
153 cvt.buf = (Uint8 *) malloc(cvt.len * cvt.len_mult);
155 memcpy(cvt.buf, pcm_data, cvt.len);
157 SDL_ConvertAudio(&cvt);
158 SDL_MixAudio(udata->stream, cvt.buf, cvt.len_cvt, sim_volume);
160 udata->num_in = cvt.len / pcm_sample_bytes;
161 udata->num_out = cvt.len_cvt / pcm_sample_bytes;
163 if (udata->debug != NULL) {
164 fwrite(cvt.buf, sizeof(Uint8), cvt.len_cvt, udata->debug);
167 free(cvt.buf);
169 else {
170 /* Convert is bad, so do silence */
171 Uint32 num = wr*obtained.channels;
172 udata->num_in = rd;
173 udata->num_out = wr;
175 switch (pcm_channel_bytes)
177 case 1:
179 Uint8 *stream = udata->stream;
180 while (num-- > 0)
181 *stream++ = obtained.silence;
182 break;
184 case 2:
186 Uint16 *stream = (Uint16 *)udata->stream;
187 while (num-- > 0)
188 *stream++ = obtained.silence;
189 break;
193 if (udata->debug != NULL) {
194 fwrite(udata->stream, sizeof(Uint8), wr, udata->debug);
197 } else {
198 udata->num_in = udata->num_out = MIN(udata->num_in, udata->num_out);
199 SDL_MixAudio(udata->stream, pcm_data,
200 udata->num_out * pcm_sample_bytes, sim_volume);
202 if (udata->debug != NULL) {
203 fwrite(pcm_data, sizeof(Uint8), udata->num_out * pcm_sample_bytes,
204 udata->debug);
209 void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
211 udata->stream = stream;
213 /* Write what we have in the PCM buffer */
214 if (pcm_data_size > 0)
215 goto start;
217 /* Audio card wants more? Get some more then. */
218 while (len > 0) {
219 if ((ssize_t)pcm_data_size <= 0) {
220 pcm_data_size = 0;
222 if (pcm_callback_for_more)
223 pcm_callback_for_more(&pcm_data, &pcm_data_size);
226 if (pcm_data_size > 0) {
227 start:
228 udata->num_in = pcm_data_size / pcm_sample_bytes;
229 udata->num_out = len / pcm_sample_bytes;
231 write_to_soundcard(udata);
233 udata->num_in *= pcm_sample_bytes;
234 udata->num_out *= pcm_sample_bytes;
236 pcm_data += udata->num_in;
237 pcm_data_size -= udata->num_in;
238 udata->stream += udata->num_out;
239 len -= udata->num_out;
240 } else {
241 DEBUGF("sdl_audio_callback: No Data.\n");
242 pcm_play_dma_stop();
243 pcm_play_dma_stopped_callback();
244 break;
249 const void * pcm_play_dma_get_peak_buffer(int *count)
251 uintptr_t addr = (uintptr_t)pcm_data;
252 *count = pcm_data_size / 4;
253 return (void *)((addr + 2) & ~3);
256 #ifdef HAVE_RECORDING
257 void pcm_rec_lock(void)
261 void pcm_rec_unlock(void)
265 void pcm_rec_dma_init(void)
269 void pcm_rec_dma_close(void)
273 void pcm_rec_dma_start(void *start, size_t size)
275 (void)start;
276 (void)size;
279 void pcm_rec_dma_stop(void)
283 void pcm_record_more(void *start, size_t size)
285 (void)start;
286 (void)size;
289 unsigned long pcm_rec_status(void)
291 return 0;
294 const void * pcm_rec_dma_get_peak_buffer(int *count)
296 *count = 0;
297 return NULL;
300 #endif /* HAVE_RECORDING */
302 void pcm_play_dma_init(void)
304 SDL_AudioSpec wanted_spec;
305 udata.debug = NULL;
307 if (debug_audio) {
308 udata.debug = fopen("audiodebug.raw", "wb");
309 DEBUGF("Audio debug file open\n");
312 /* Set 16-bit stereo audio at 44Khz */
313 wanted_spec.freq = 44100;
314 wanted_spec.format = AUDIO_S16SYS;
315 wanted_spec.channels = 2;
316 wanted_spec.samples = 2048;
317 wanted_spec.callback =
318 (void (SDLCALL *)(void *userdata,
319 Uint8 *stream, int len))sdl_audio_callback;
320 wanted_spec.userdata = &udata;
322 /* Open the audio device and start playing sound! */
323 if(SDL_OpenAudio(&wanted_spec, &obtained) < 0) {
324 fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
325 return;
328 switch (obtained.format)
330 case AUDIO_U8:
331 case AUDIO_S8:
332 pcm_channel_bytes = 1;
333 break;
334 case AUDIO_U16LSB:
335 case AUDIO_S16LSB:
336 case AUDIO_U16MSB:
337 case AUDIO_S16MSB:
338 pcm_channel_bytes = 2;
339 break;
340 default:
341 fprintf(stderr, "Unknown sample format obtained: %u\n",
342 (unsigned)obtained.format);
343 return;
346 pcm_sample_bytes = obtained.channels * pcm_channel_bytes;
348 pcm_dma_apply_settings_nolock();
351 void pcm_postinit(void)
355 #endif /* CONFIG_CODEC == SWCODEC */
358 * Audio Hardware api. Make them do nothing as we cannot properly simulate with
359 * SDL. if we used DSP we would run code that doesn't actually run on the target
361 void audiohw_set_volume(int volume)
363 sim_volume = SDL_MIX_MAXVOLUME * ((volume - VOLUME_MIN) / 10) / (VOLUME_RANGE / 10);
365 #if defined(AUDIOHW_HAVE_PRESCALER)
366 void audiohw_set_prescaler(int value) { (void)value; }
367 #endif
368 #if defined(AUDIOHW_HAVE_BALANCE)
369 void audiohw_set_balance(int value) { (void)value; }
370 #endif
371 #if defined(AUDIOHW_HAVE_BASS)
372 void audiohw_set_bass(int value) { (void)value; }
373 #endif
374 #if defined(AUDIOHW_HAVE_TREBLE)
375 void audiohw_set_treble(int value) { (void)value; }
376 #endif
377 #if CONFIG_CODEC != SWCODEC
378 void audiohw_set_channel(int value) { (void)value; }
379 void audiohw_set_stereo_width(int value){ (void)value; }
380 #endif
381 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
382 void audiohw_set_bass_cutoff(value) { (void)value; }
383 #endif
384 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
385 void audiohw_set_treble_cutoff(value) { (void)value; }
386 #endif
387 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
388 int mas_codec_readreg(int reg)
390 (void)reg;
391 return 0;
394 int mas_codec_writereg(int reg, unsigned int val)
396 (void)reg;
397 (void)val;
398 return 0;
400 int mas_writemem(int bank, int addr, const unsigned long* src, int len)
402 (void)bank;
403 (void)addr;
404 (void)src;
405 (void)len;
406 return 0;
408 #endif