1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
32 #include "pcm_sampr.h"
35 /*#define LOGF_ENABLE*/
38 static int sim_volume
= 0;
40 #if CONFIG_CODEC == SWCODEC
41 static int cvt_status
= -1;
43 static Uint8
* pcm_data
;
44 static size_t pcm_data_size
;
45 static size_t pcm_sample_bytes
;
46 static size_t pcm_channel_bytes
;
48 static struct pcm_udata
56 static SDL_AudioSpec obtained
;
57 static SDL_AudioCVT cvt
;
59 extern bool debug_audio
;
62 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
65 void pcm_play_lock(void)
70 void pcm_play_unlock(void)
75 static void pcm_dma_apply_settings_nolock(void)
77 cvt_status
= SDL_BuildAudioCVT(&cvt
, AUDIO_S16SYS
, 2, pcm_sampr
,
78 obtained
.format
, obtained
.channels
, obtained
.freq
);
81 cvt
.len_ratio
= (double)obtained
.freq
/ (double)pcm_sampr
;
85 void pcm_dma_apply_settings(void)
88 pcm_dma_apply_settings_nolock();
92 void pcm_play_dma_start(const void *addr
, size_t size
)
94 pcm_dma_apply_settings_nolock();
96 pcm_data
= (Uint8
*) addr
;
102 void pcm_play_dma_stop(void)
105 if (udata
.debug
!= NULL
) {
108 DEBUGF("Audio debug file closed\n");
112 void pcm_play_dma_pause(bool pause
)
120 size_t pcm_get_bytes_waiting(void)
122 return pcm_data_size
;
125 extern int sim_volume
; /* in firmware/sound.c */
126 static void write_to_soundcard(struct pcm_udata
*udata
) {
127 if (debug_audio
&& (udata
->debug
== NULL
)) {
128 udata
->debug
= fopen("audiodebug.raw", "ab");
129 DEBUGF("Audio debug file open\n");
133 Uint32 rd
= udata
->num_in
;
134 Uint32 wr
= (double)rd
* cvt
.len_ratio
;
136 if (wr
> udata
->num_out
) {
138 rd
= (double)wr
/ cvt
.len_ratio
;
140 if (rd
> udata
->num_in
)
143 wr
= (double)rd
* cvt
.len_ratio
;
147 if (wr
== 0 || rd
== 0)
149 udata
->num_out
= udata
->num_in
= 0;
153 if (cvt_status
> 0) {
154 cvt
.len
= rd
* pcm_sample_bytes
;
155 cvt
.buf
= (Uint8
*) malloc(cvt
.len
* cvt
.len_mult
);
157 memcpy(cvt
.buf
, pcm_data
, cvt
.len
);
159 SDL_ConvertAudio(&cvt
);
160 SDL_MixAudio(udata
->stream
, cvt
.buf
, cvt
.len_cvt
, sim_volume
);
162 udata
->num_in
= cvt
.len
/ pcm_sample_bytes
;
163 udata
->num_out
= cvt
.len_cvt
/ pcm_sample_bytes
;
165 if (udata
->debug
!= NULL
) {
166 fwrite(cvt
.buf
, sizeof(Uint8
), cvt
.len_cvt
, udata
->debug
);
172 /* Convert is bad, so do silence */
173 Uint32 num
= wr
*obtained
.channels
;
177 switch (pcm_channel_bytes
)
181 Uint8
*stream
= udata
->stream
;
183 *stream
++ = obtained
.silence
;
188 Uint16
*stream
= (Uint16
*)udata
->stream
;
190 *stream
++ = obtained
.silence
;
195 if (udata
->debug
!= NULL
) {
196 fwrite(udata
->stream
, sizeof(Uint8
), wr
, udata
->debug
);
200 udata
->num_in
= udata
->num_out
= MIN(udata
->num_in
, udata
->num_out
);
201 SDL_MixAudio(udata
->stream
, pcm_data
,
202 udata
->num_out
* pcm_sample_bytes
, sim_volume
);
204 if (udata
->debug
!= NULL
) {
205 fwrite(pcm_data
, sizeof(Uint8
), udata
->num_out
* pcm_sample_bytes
,
211 static void sdl_audio_callback(struct pcm_udata
*udata
, Uint8
*stream
, int len
)
213 logf("sdl_audio_callback: len %d, pcm %d\n", len
, pcm_data_size
);
214 udata
->stream
= stream
;
216 /* Write what we have in the PCM buffer */
217 if (pcm_data_size
> 0)
220 /* Audio card wants more? Get some more then. */
222 if ((ssize_t
)pcm_data_size
<= 0) {
224 if (pcm_callback_for_more
)
225 pcm_callback_for_more(&pcm_data
, &pcm_data_size
);
228 if (pcm_data_size
> 0) {
230 udata
->num_in
= pcm_data_size
/ pcm_sample_bytes
;
231 udata
->num_out
= len
/ pcm_sample_bytes
;
233 write_to_soundcard(udata
);
235 udata
->num_in
*= pcm_sample_bytes
;
236 udata
->num_out
*= pcm_sample_bytes
;
238 pcm_data
+= udata
->num_in
;
239 pcm_data_size
-= udata
->num_in
;
240 udata
->stream
+= udata
->num_out
;
241 len
-= udata
->num_out
;
243 DEBUGF("sdl_audio_callback: No Data.\n");
245 pcm_play_dma_stopped_callback();
251 const void * pcm_play_dma_get_peak_buffer(int *count
)
253 uintptr_t addr
= (uintptr_t)pcm_data
;
254 *count
= pcm_data_size
/ 4;
255 return (void *)((addr
+ 2) & ~3);
258 #ifdef HAVE_RECORDING
259 void pcm_rec_lock(void)
263 void pcm_rec_unlock(void)
267 void pcm_rec_dma_init(void)
271 void pcm_rec_dma_close(void)
275 void pcm_rec_dma_start(void *start
, size_t size
)
281 void pcm_rec_dma_stop(void)
285 void pcm_rec_dma_record_more(void *start
, size_t size
)
291 unsigned long pcm_rec_status(void)
296 const void * pcm_rec_dma_get_peak_buffer(void)
301 #endif /* HAVE_RECORDING */
303 void pcm_play_dma_init(void)
305 SDL_AudioSpec wanted_spec
;
309 udata
.debug
= fopen("audiodebug.raw", "wb");
310 DEBUGF("Audio debug file open\n");
313 /* Set 16-bit stereo audio at 44Khz */
314 wanted_spec
.freq
= 44100;
315 wanted_spec
.format
= AUDIO_S16SYS
;
316 wanted_spec
.channels
= 2;
317 wanted_spec
.samples
= 2048;
318 wanted_spec
.callback
=
319 (void (SDLCALL
*)(void *userdata
,
320 Uint8
*stream
, int len
))sdl_audio_callback
;
321 wanted_spec
.userdata
= &udata
;
323 /* Open the audio device and start playing sound! */
324 if(SDL_OpenAudio(&wanted_spec
, &obtained
) < 0) {
325 fprintf(stderr
, "Unable to open audio: %s\n", SDL_GetError());
329 switch (obtained
.format
)
333 pcm_channel_bytes
= 1;
339 pcm_channel_bytes
= 2;
342 fprintf(stderr
, "Unknown sample format obtained: %u\n",
343 (unsigned)obtained
.format
);
347 pcm_sample_bytes
= obtained
.channels
* pcm_channel_bytes
;
349 pcm_dma_apply_settings_nolock();
352 void pcm_postinit(void)
356 #endif /* CONFIG_CODEC == SWCODEC */
359 * Audio Hardware api. Make them do nothing as we cannot properly simulate with
360 * SDL. if we used DSP we would run code that doesn't actually run on the target
362 void audiohw_set_volume(int volume
)
364 sim_volume
= SDL_MIX_MAXVOLUME
* ((volume
- VOLUME_MIN
) / 10) / (VOLUME_RANGE
/ 10);
366 #if defined(AUDIOHW_HAVE_PRESCALER)
367 void audiohw_set_prescaler(int value
) { (void)value
; }
369 #if defined(AUDIOHW_HAVE_BALANCE)
370 void audiohw_set_balance(int value
) { (void)value
; }
372 #if defined(AUDIOHW_HAVE_BASS)
373 void audiohw_set_bass(int value
) { (void)value
; }
375 #if defined(AUDIOHW_HAVE_TREBLE)
376 void audiohw_set_treble(int value
) { (void)value
; }
378 #if CONFIG_CODEC != SWCODEC
379 void audiohw_set_channel(int value
) { (void)value
; }
380 void audiohw_set_stereo_width(int value
){ (void)value
; }
382 #if defined(AUDIOHW_HAVE_BASS_CUTOFF)
383 void audiohw_set_bass_cutoff(int value
) { (void)value
; }
385 #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
386 void audiohw_set_treble_cutoff(int value
){ (void)value
; }
388 /* EQ-based tone controls */
389 #if defined(AUDIOHW_HAVE_EQ)
390 void audiohw_set_eq_band_gain(unsigned int band
, int value
)
391 { (void)band
; (void)value
; }
393 #if defined(AUDIOHW_HAVE_EQ_FREQUENCY)
394 void audiohw_set_eq_band_frequency(unsigned int band
, int value
)
395 { (void)band
; (void)value
; }
397 #if defined(AUDIOHW_HAVE_EQ_WIDTH)
398 void audiohw_set_eq_band_width(unsigned int band
, int value
)
399 { (void)band
; (void)value
; }
401 #if defined(AUDIOHW_HAVE_DEPTH_3D)
402 void audiohw_set_depth_3d(int value
)
405 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
406 int mas_codec_readreg(int reg
)
412 int mas_codec_writereg(int reg
, unsigned int val
)
418 int mas_writemem(int bank
, int addr
, const unsigned long* src
, int len
)