2
CD-DA "Red Book" audio sound hardware handler
3
Relies on the actual CD logic and reading in cdrom.c.
10
typedef struct _cdda_info cdda_info;
13
sound_stream * stream;
16
INT8 audio_playing, audio_pause, audio_ended_normally;
17
UINT32 audio_lba, audio_length;
24
INLINE cdda_info *get_safe_token(device_t *device)
26
assert(device != NULL);
27
assert(device->type() == CDDA);
28
return (cdda_info *)downcast<legacy_device_base *>(device)->token();
31
#define MAX_SECTORS ( 4 )
33
static void get_audio_data(cdda_info *info, stream_sample_t *bufL, stream_sample_t *bufR, UINT32 samples_wanted);
36
/*-------------------------------------------------
37
cdda_update - stream update callback
38
-------------------------------------------------*/
40
static STREAM_UPDATE( cdda_update )
42
cdda_info *info = (cdda_info *)param;
43
get_audio_data(info, &outputs[0][0], &outputs[1][0], samples);
47
/*-------------------------------------------------
48
DEVICE_START( cdda ) - audio start callback
49
-------------------------------------------------*/
51
static DEVICE_START( cdda )
53
//const struct CDDAinterface *intf;
54
cdda_info *info = get_safe_token(device);
56
/* allocate an audio cache */
57
info->audio_cache = auto_alloc_array( device->machine(), UINT8, CD_MAX_SECTOR_DATA * MAX_SECTORS );
59
//intf = (const struct CDDAinterface *)device->static_config();
61
info->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, info, cdda_update);
63
device->save_item( NAME(info->audio_playing) );
64
device->save_item( NAME(info->audio_pause) );
65
device->save_item( NAME(info->audio_ended_normally) );
66
device->save_item( NAME(info->audio_lba) );
67
device->save_item( NAME(info->audio_length) );
68
device->save_pointer( NAME(info->audio_cache), CD_MAX_SECTOR_DATA * MAX_SECTORS );
69
device->save_item( NAME(info->audio_samples) );
70
device->save_item( NAME(info->audio_bptr) );
74
/*-------------------------------------------------
75
cdda_set_cdrom - set the CD-ROM file for the
77
-------------------------------------------------*/
79
void cdda_set_cdrom(device_t *device, void *file)
81
cdda_info *info = get_safe_token(device);
82
info->disc = (cdrom_file *)file;
86
/*-------------------------------------------------
87
cdda_from_cdrom - find the CDDA stream
88
that references the given CD-ROM file
89
-------------------------------------------------*/
91
device_t *cdda_from_cdrom(running_machine &machine, void *file)
93
device_sound_interface *sound = NULL;
95
for (bool gotone = machine.devicelist().first(sound); gotone; gotone = sound->next(sound))
96
if (sound->device().type() == CDDA)
98
cdda_info *info = get_safe_token(*sound);
99
if (info->disc == file)
107
/*-------------------------------------------------
108
cdda_start_audio - begin playback of a Red
110
-------------------------------------------------*/
112
void cdda_start_audio(device_t *device, UINT32 startlba, UINT32 numblocks)
114
cdda_info *info = get_safe_token(device);
116
info->stream->update();
117
info->audio_playing = TRUE;
118
info->audio_pause = FALSE;
119
info->audio_ended_normally = FALSE;
120
info->audio_lba = startlba;
121
info->audio_length = numblocks;
125
/*-------------------------------------------------
126
cdda_stop_audio - stop playback of a Red Book
128
-------------------------------------------------*/
130
void cdda_stop_audio(device_t *device)
132
cdda_info *info = get_safe_token(device);
134
info->stream->update();
135
info->audio_playing = FALSE;
136
info->audio_ended_normally = TRUE;
140
/*-------------------------------------------------
141
cdda_pause_audio - pause/unpause playback of
142
a Red Book audio track
143
-------------------------------------------------*/
145
void cdda_pause_audio(device_t *device, int pause)
147
cdda_info *info = get_safe_token(device);
149
info->stream->update();
150
info->audio_pause = pause;
154
/*-------------------------------------------------
155
cdda_get_audio_lba - returns the current LBA
156
(physical sector) during Red Book playback
157
-------------------------------------------------*/
159
UINT32 cdda_get_audio_lba(device_t *device)
161
cdda_info *info = get_safe_token(device);
163
info->stream->update();
164
return info->audio_lba;
168
/*-------------------------------------------------
169
cdda_audio_active - returns Red Book audio
171
-------------------------------------------------*/
173
int cdda_audio_active(device_t *device)
175
cdda_info *info = get_safe_token(device);
177
info->stream->update();
178
return info->audio_playing;
182
/*-------------------------------------------------
183
cdda_audio_paused - returns if Red Book
185
-------------------------------------------------*/
187
int cdda_audio_paused(device_t *device)
189
cdda_info *info = get_safe_token(device);
190
return info->audio_pause;
194
/*-------------------------------------------------
195
cdda_audio_ended - returns if a Red Book
196
track reached it's natural end
197
-------------------------------------------------*/
199
int cdda_audio_ended(device_t *device)
201
cdda_info *info = get_safe_token(device);
202
return info->audio_ended_normally;
206
/*-------------------------------------------------
207
get_audio_data - reads Red Book data off
208
the disc if playback is in progress and
209
converts it to 2 16-bit 44.1 kHz streams
210
-------------------------------------------------*/
212
static void get_audio_data(cdda_info *info, stream_sample_t *bufL, stream_sample_t *bufR, UINT32 samples_wanted)
214
int i, sectoread, remaining;
215
INT16 *audio_cache = (INT16 *) info->audio_cache;
217
/* if no file, audio not playing, audio paused, or out of disc data,
219
if (!info->disc || !info->audio_playing || info->audio_pause || (!info->audio_length && !info->audio_samples))
221
if( info->disc && info->audio_playing && !info->audio_pause && !info->audio_length )
223
info->audio_playing = FALSE;
224
info->audio_ended_normally = TRUE;
227
memset(bufL, 0, sizeof(stream_sample_t)*samples_wanted);
228
memset(bufR, 0, sizeof(stream_sample_t)*samples_wanted);
232
/* if we've got enough samples, just feed 'em out */
233
if (samples_wanted <= info->audio_samples)
235
for (i = 0; i < samples_wanted; i++)
237
*bufL++ = audio_cache[ info->audio_bptr++ ];
238
*bufR++ = audio_cache[ info->audio_bptr++ ];
241
info->audio_samples -= samples_wanted;
245
/* we don't have enough, so first feed what we've got */
246
for (i = 0; i < info->audio_samples; i++)
248
*bufL++ = audio_cache[ info->audio_bptr++ ];
249
*bufR++ = audio_cache[ info->audio_bptr++ ];
252
/* remember how much left for later */
253
remaining = samples_wanted - info->audio_samples;
255
/* reset the buffer and get what we can from the disc */
256
info->audio_samples = 0;
257
if (info->audio_length >= MAX_SECTORS)
259
sectoread = MAX_SECTORS;
263
sectoread = info->audio_length;
266
for (i = 0; i < sectoread; i++)
268
cdrom_read_data(info->disc, info->audio_lba, &info->audio_cache[CD_MAX_SECTOR_DATA*i], CD_TRACK_AUDIO);
273
info->audio_samples = (CD_MAX_SECTOR_DATA*sectoread)/4;
274
info->audio_length -= sectoread;
276
/* CD-DA data on the disc is big-endian, flip if we're not */
277
if (ENDIANNESS_NATIVE == ENDIANNESS_LITTLE)
279
for( i = 0; i < info->audio_samples * 2; i++ )
281
audio_cache[ i ] = BIG_ENDIANIZE_INT16( audio_cache[ i ] );
285
/* reset feedout ptr */
286
info->audio_bptr = 0;
288
/* we've got data, feed it out by calling ourselves recursively */
289
get_audio_data(info, bufL, bufR, remaining);
292
/*-------------------------------------------------
293
cdda_set_volume - sets CD-DA volume level
294
for both speakers, used for fade in/out effects
295
-------------------------------------------------*/
297
void cdda_set_volume(device_t *device,int volume)
299
cdda_info *cdda = get_safe_token(device);
301
cdda->stream->set_output_gain(0,volume / 100.0);
302
cdda->stream->set_output_gain(1,volume / 100.0);
305
/*-------------------------------------------------
306
cdda_set_channel_volume - sets CD-DA volume level
307
for either speaker, used for fade in/out effects
308
-------------------------------------------------*/
310
void cdda_set_channel_volume(device_t *device, int channel, int volume)
312
cdda_info *cdda = get_safe_token(device);
315
cdda->stream->set_output_gain(0,volume / 100.0);
317
cdda->stream->set_output_gain(1,volume / 100.0);
320
/**************************************************************************
322
**************************************************************************/
324
DEVICE_GET_INFO( cdda )
328
/* --- the following bits of info are returned as 64-bit signed integers --- */
329
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(cdda_info); break;
331
/* --- the following bits of info are returned as pointers to data or functions --- */
332
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( cdda ); break;
333
case DEVINFO_FCT_STOP: /* nothing */ break;
334
case DEVINFO_FCT_RESET: /* nothing */ break;
336
/* --- the following bits of info are returned as NULL-terminated strings --- */
337
case DEVINFO_STR_NAME: strcpy(info->s, "CD/DA"); break;
338
case DEVINFO_STR_FAMILY: strcpy(info->s, "CD Audio"); break;
339
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
340
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
341
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
346
DEFINE_LEGACY_SOUND_DEVICE(CDDA, cdda);