diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 223e1411c..37615a32e 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -238,6 +238,16 @@ cdrom_seek(cdrom_t *dev, uint32_t pos) } +int +cdrom_is_pre(cdrom_t *dev, uint32_t lba) +{ + if (dev->ops && dev->ops->is_track_pre) + return dev->ops->is_track_pre(dev, lba); + + return 0; +} + + int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len) { diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 2df0801c3..91e4992b4 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -155,12 +155,28 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) if (track == -1) return 0; else { - cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr); + cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr); return attr == AUDIO_TRACK; } } +static int +image_is_track_pre(cdrom_t *dev, uint32_t lba) +{ + cd_img_t *img = (cd_img_t *)dev->image; + int track; + + /* GetTrack requires LBA. */ + track = cdi_get_track(img, lba); + + if (track != -1) + return cdi_get_audio_track_pre(img, track); + + return 0; +} + + static int image_sector_size(struct cdrom *dev, uint32_t lba) { @@ -231,6 +247,7 @@ static const cdrom_ops_t cdrom_image_ops = { image_get_tracks, image_get_track_info, image_get_subchannel, + image_is_track_pre, image_sector_size, image_read_sector, image_track_type, diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index cf4cb0005..ae6e4bb39 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -272,6 +272,18 @@ cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_ } +int +cdi_get_audio_track_pre(cd_img_t *cdi, int track) +{ + track_t *trk = &cdi->tracks[track - 1]; + + if ((track < 1) || (track > cdi->tracks_num)) + return 0; + + return trk->pre; +} + + /* This replaces both Info and EndInfo, they are specified by a variable. */ int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) @@ -709,6 +721,25 @@ cdi_cue_get_frame(uint64_t *frames, char **line) } +static int +cdi_cue_get_flags(track_t *cur, char **line) +{ + char temp[128], temp2[128]; + int success; + + success = cdi_cue_get_buffer(temp, line, 0); + if (! success) return 0; + + memset(temp2, 0x00, sizeof(temp2)); + success = sscanf(temp, "%s", temp2) == 1; + if (! success) return 0; + + cur->pre = (strstr(temp2, "PRE") != NULL); + + return 1; +} + + static int cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) { @@ -850,6 +881,8 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) trk.form = 0; trk.mode2 = 0; + trk.pre = 0; + if (!strcmp(type, "AUDIO")) { trk.sector_size = RAW_SECTOR_SIZE; trk.attr = AUDIO_TRACK; @@ -964,7 +997,9 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) } } else if (!strcmp(command, "PREGAP")) success = cdi_cue_get_frame(&cur_pregap, &line); - else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "FLAGS") || !strcmp(command, "ISRC") || + else if (!strcmp(command, "FLAGS")) + success = cdi_cue_get_flags(&trk, &line); + else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) { /* Ignored commands. */ diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 759932198..95b806d30 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -83,6 +83,7 @@ typedef struct { void (*get_tracks)(struct cdrom *dev, int *first, int *last); void (*get_track_info)(struct cdrom *dev, uint32_t track, int end, track_info_t *ti); void (*get_subchannel)(struct cdrom *dev, uint32_t lba, subchannel_t *subc); + int (*is_track_pre)(struct cdrom *dev, uint32_t lba); int (*sector_size)(struct cdrom *dev, uint32_t lba); int (*read_sector)(struct cdrom *dev, int type, uint8_t *b, uint32_t lba); int (*track_type)(struct cdrom *dev, uint32_t lba); @@ -136,6 +137,7 @@ extern cdrom_t cdrom[CDROM_NUM]; extern int cdrom_lba_to_msf_accurate(int lba); extern double cdrom_seek_time(cdrom_t *dev); extern void cdrom_stop(cdrom_t *dev); +extern int cdrom_is_pre(cdrom_t *dev, uint32_t lba); extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len); extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf); extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit); diff --git a/src/include/86box/cdrom_image_backend.h b/src/include/86box/cdrom_image_backend.h index 5d5901320..74be1df69 100644 --- a/src/include/86box/cdrom_image_backend.h +++ b/src/include/86box/cdrom_image_backend.h @@ -58,7 +58,7 @@ typedef struct { typedef struct { int number, track_number, attr, sector_size, - mode2, form; + mode2, form, pre, pad; uint64_t start, length, skip; track_file_t *file; @@ -75,6 +75,7 @@ extern void cdi_close(cd_img_t *cdi); extern int cdi_set_device(cd_img_t *cdi, const char *path); extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out); extern int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out); +extern int cdi_get_audio_track_pre(cd_img_t *cdi, int track); extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr); extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr); extern int cdi_get_track(cd_img_t *cdi, uint32_t sector); diff --git a/src/sound/sound.c b/src/sound/sound.c index fa5d180ac..663983738 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -212,7 +212,8 @@ sound_cd_clean_buffers(void) static void sound_cd_thread(void *param) { - int c, r, i, channel_select[2]; + uint32_t lba; + int c, r, i, pre, channel_select[2]; double audio_vol_l, audio_vol_r; double cd_buffer_temp[2] = {0.0, 0.0}; @@ -231,9 +232,11 @@ sound_cd_thread(void *param) if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || (cdrom[i].cd_status == CD_STATUS_EMPTY)) continue; + lba = cdrom[i].seek_pos; r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2); if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r) continue; + pre = cdrom_is_pre(&(cdrom[i]), lba); if (cdrom[i].get_volume) { audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0)); @@ -277,6 +280,9 @@ sound_cd_thread(void *param) cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */ cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */ + + if (pre) + cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */ } if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) { @@ -286,6 +292,9 @@ sound_cd_thread(void *param) cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */ cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */ + + if (pre) + cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */ } /* Apply sound card CD volume and filters */