Implemented CD Audio de-emphasizing for pre-emphasized tracks, closes #1623.

This commit is contained in:
OBattler
2021-09-02 20:52:30 +02:00
parent 84f4b8cac7
commit 5b972fc477
6 changed files with 78 additions and 4 deletions

View File

@@ -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)
{

View File

@@ -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,

View File

@@ -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. */

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 */