mirror of
https://github.com/WonderfulToolchain/psxavenc.git
synced 2025-09-18 20:41:56 +00:00
Clean up, implement new SPU-ADPCM looping options
This commit is contained in:
@@ -29,8 +29,8 @@ freely, subject to the following restrictions:
|
||||
#define SHIFT_RANGE_4BPS 12
|
||||
#define SHIFT_RANGE_8BPS 8
|
||||
|
||||
#define ADPCM_FILTER_COUNT 5
|
||||
#define XA_ADPCM_FILTER_COUNT 4
|
||||
#define ADPCM_FILTER_COUNT 5
|
||||
#define XA_ADPCM_FILTER_COUNT 4
|
||||
#define SPU_ADPCM_FILTER_COUNT 5
|
||||
|
||||
static const int16_t filter_k1[ADPCM_FILTER_COUNT] = {0, 60, 115, 98, 122};
|
||||
@@ -54,7 +54,7 @@ static int find_min_shift(const psx_audio_encoder_channel_state_t *state, int16_
|
||||
|
||||
int32_t s_min = 0;
|
||||
int32_t s_max = 0;
|
||||
for (int i = 0; i < 28; i++) {
|
||||
for (int i = 0; i < PSX_AUDIO_SPU_SAMPLES_PER_BLOCK; i++) {
|
||||
int32_t raw_sample = (i >= sample_limit) ? 0 : samples[i * pitch];
|
||||
int32_t previous_values = (k1*prev1 + k2*prev2 + (1<<5))>>6;
|
||||
int32_t sample = raw_sample - previous_values;
|
||||
@@ -87,7 +87,7 @@ static uint8_t attempt_to_encode(psx_audio_encoder_channel_state_t *outstate, co
|
||||
|
||||
outstate->mse = 0;
|
||||
|
||||
for (int i = 0; i < 28; i++) {
|
||||
for (int i = 0; i < PSX_AUDIO_SPU_SAMPLES_PER_BLOCK; i++) {
|
||||
int32_t sample = ((i >= sample_limit) ? 0 : samples[i * pitch]) + outstate->qerr;
|
||||
int32_t previous_values = (k1*outstate->prev1 + k2*outstate->prev2 + (1<<5))>>6;
|
||||
int32_t sample_enc = sample - previous_values;
|
||||
@@ -205,25 +205,17 @@ uint32_t psx_audio_xa_get_buffer_size(psx_audio_xa_settings_t settings, int samp
|
||||
}
|
||||
|
||||
uint32_t psx_audio_spu_get_buffer_size(int sample_count) {
|
||||
return ((sample_count + 27) / 28) << 4;
|
||||
return ((sample_count + PSX_AUDIO_SPU_SAMPLES_PER_BLOCK - 1) / PSX_AUDIO_SPU_SAMPLES_PER_BLOCK) << 4;
|
||||
}
|
||||
|
||||
uint32_t psx_audio_xa_get_buffer_size_per_sector(psx_audio_xa_settings_t settings) {
|
||||
return settings.format == PSX_AUDIO_XA_FORMAT_XA ? 2336 : 2352;
|
||||
}
|
||||
|
||||
uint32_t psx_audio_spu_get_buffer_size_per_block(void) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
uint32_t psx_audio_xa_get_samples_per_sector(psx_audio_xa_settings_t settings) {
|
||||
return (((settings.bits_per_sample == 8) ? 112 : 224) >> (settings.stereo ? 1 : 0)) * 18;
|
||||
}
|
||||
|
||||
uint32_t psx_audio_spu_get_samples_per_block(void) {
|
||||
return 28;
|
||||
}
|
||||
|
||||
uint32_t psx_audio_xa_get_sector_interleave(psx_audio_xa_settings_t settings) {
|
||||
// 1/2 interleave for 37800 Hz 8-bit stereo at 1x speed
|
||||
int interleave = settings.stereo ? 2 : 4;
|
||||
@@ -307,14 +299,14 @@ int psx_audio_xa_encode_simple(psx_audio_xa_settings_t settings, int16_t* sample
|
||||
}
|
||||
|
||||
int psx_audio_spu_encode(psx_audio_encoder_channel_state_t *state, int16_t* samples, int sample_count, int pitch, uint8_t *output) {
|
||||
uint8_t prebuf[28];
|
||||
uint8_t prebuf[PSX_AUDIO_SPU_SAMPLES_PER_BLOCK];
|
||||
uint8_t *buffer = output;
|
||||
|
||||
for (int i = 0; i < sample_count; i += 28, buffer += 16) {
|
||||
for (int i = 0; i < sample_count; i += PSX_AUDIO_SPU_SAMPLES_PER_BLOCK, buffer += PSX_AUDIO_SPU_BLOCK_SIZE) {
|
||||
buffer[0] = encode(state, samples + i * pitch, sample_count - i, pitch, prebuf, 0, 1, SPU_ADPCM_FILTER_COUNT, SHIFT_RANGE_4BPS);
|
||||
buffer[1] = 0;
|
||||
|
||||
for (int j = 0; j < 28; j+=2) {
|
||||
for (int j = 0; j < PSX_AUDIO_SPU_SAMPLES_PER_BLOCK; j+=2) {
|
||||
buffer[2 + (j>>1)] = (prebuf[j] & 0x0F) | (prebuf[j+1] << 4);
|
||||
}
|
||||
}
|
||||
@@ -327,24 +319,24 @@ int psx_audio_spu_encode_simple(int16_t* samples, int sample_count, uint8_t *out
|
||||
memset(&state, 0, sizeof(psx_audio_encoder_channel_state_t));
|
||||
int length = psx_audio_spu_encode(&state, samples, sample_count, 1, output);
|
||||
|
||||
if (length >= 32) {
|
||||
if (length >= PSX_AUDIO_SPU_BLOCK_SIZE) {
|
||||
uint8_t *last_block = output + length - PSX_AUDIO_SPU_BLOCK_SIZE;
|
||||
|
||||
if (loop_start < 0) {
|
||||
//output[1] = PSX_AUDIO_SPU_LOOP_START;
|
||||
output[length - 16 + 1] = PSX_AUDIO_SPU_LOOP_END;
|
||||
last_block[1] |= PSX_AUDIO_SPU_LOOP_END;
|
||||
|
||||
// Insert trailing looping block
|
||||
memset(output + length, 0, PSX_AUDIO_SPU_BLOCK_SIZE);
|
||||
output[length + 1] = PSX_AUDIO_SPU_LOOP_START | PSX_AUDIO_SPU_LOOP_END;
|
||||
|
||||
length += PSX_AUDIO_SPU_BLOCK_SIZE;
|
||||
} else {
|
||||
psx_audio_spu_set_flag_at_sample(output, loop_start, PSX_AUDIO_SPU_LOOP_START);
|
||||
output[length - 16 + 1] = PSX_AUDIO_SPU_LOOP_REPEAT;
|
||||
int loop_start_offset = loop_start / PSX_AUDIO_SPU_SAMPLES_PER_BLOCK * PSX_AUDIO_SPU_BLOCK_SIZE;
|
||||
|
||||
last_block[1] |= PSX_AUDIO_SPU_LOOP_REPEAT;
|
||||
output[loop_start_offset + 1] |= PSX_AUDIO_SPU_LOOP_START;
|
||||
}
|
||||
} else if (length >= 16) {
|
||||
output[1] = PSX_AUDIO_SPU_LOOP_START | PSX_AUDIO_SPU_LOOP_END;
|
||||
if (loop_start >= 0)
|
||||
output[1] |= PSX_AUDIO_SPU_LOOP_REPEAT;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void psx_audio_spu_set_flag_at_sample(uint8_t* spu_data, int sample_pos, int flag) {
|
||||
int buffer_pos = (sample_pos / 28) << 4;
|
||||
spu_data[buffer_pos + 1] = flag;
|
||||
}
|
||||
|
@@ -28,8 +28,13 @@ freely, subject to the following restrictions:
|
||||
|
||||
// audio.c
|
||||
|
||||
#define PSX_AUDIO_XA_FREQ_SINGLE 18900
|
||||
#define PSX_AUDIO_XA_FREQ_DOUBLE 37800
|
||||
#define PSX_AUDIO_SPU_BLOCK_SIZE 16
|
||||
#define PSX_AUDIO_SPU_SAMPLES_PER_BLOCK 28
|
||||
|
||||
enum {
|
||||
PSX_AUDIO_XA_FREQ_SINGLE = 18900,
|
||||
PSX_AUDIO_XA_FREQ_DOUBLE = 37800
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PSX_AUDIO_XA_FORMAT_XA, // .xa file
|
||||
@@ -56,23 +61,22 @@ typedef struct {
|
||||
psx_audio_encoder_channel_state_t right;
|
||||
} psx_audio_encoder_state_t;
|
||||
|
||||
#define PSX_AUDIO_SPU_LOOP_END 1
|
||||
#define PSX_AUDIO_SPU_LOOP_REPEAT 3
|
||||
#define PSX_AUDIO_SPU_LOOP_START 4
|
||||
enum {
|
||||
PSX_AUDIO_SPU_LOOP_END = 1 << 0,
|
||||
PSX_AUDIO_SPU_LOOP_REPEAT = 3 << 0,
|
||||
PSX_AUDIO_SPU_LOOP_START = 1 << 2
|
||||
};
|
||||
|
||||
uint32_t psx_audio_xa_get_buffer_size(psx_audio_xa_settings_t settings, int sample_count);
|
||||
uint32_t psx_audio_spu_get_buffer_size(int sample_count);
|
||||
uint32_t psx_audio_xa_get_buffer_size_per_sector(psx_audio_xa_settings_t settings);
|
||||
uint32_t psx_audio_spu_get_buffer_size_per_block(void);
|
||||
uint32_t psx_audio_xa_get_samples_per_sector(psx_audio_xa_settings_t settings);
|
||||
uint32_t psx_audio_spu_get_samples_per_block(void);
|
||||
uint32_t psx_audio_xa_get_sector_interleave(psx_audio_xa_settings_t settings);
|
||||
int psx_audio_xa_encode(psx_audio_xa_settings_t settings, psx_audio_encoder_state_t *state, int16_t* samples, int sample_count, uint8_t *output);
|
||||
int psx_audio_xa_encode_simple(psx_audio_xa_settings_t settings, int16_t* samples, int sample_count, uint8_t *output);
|
||||
int psx_audio_spu_encode(psx_audio_encoder_channel_state_t *state, int16_t* samples, int sample_count, int pitch, uint8_t *output);
|
||||
int psx_audio_spu_encode_simple(int16_t* samples, int sample_count, uint8_t *output, int loop_start);
|
||||
void psx_audio_xa_encode_finalize(psx_audio_xa_settings_t settings, uint8_t *output, int output_length);
|
||||
void psx_audio_spu_set_flag_at_sample(uint8_t* spu_data, int sample_pos, int flag);
|
||||
|
||||
// cdrom.c
|
||||
|
||||
@@ -115,25 +119,29 @@ _Static_assert(sizeof(psx_cdrom_sector_mode2_t) == PSX_CDROM_SECTOR_SIZE, "Inval
|
||||
|
||||
#define PSX_CDROM_SECTOR_XA_CHANNEL_MASK 0x1F
|
||||
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_EOR 0x01
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_VIDEO 0x02
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_AUDIO 0x04
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_DATA 0x08
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_TRIGGER 0x10
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_FORM2 0x20
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_RT 0x40
|
||||
#define PSX_CDROM_SECTOR_XA_SUBMODE_EOF 0x80
|
||||
enum {
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_EOR = 1 << 0,
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_VIDEO = 1 << 1,
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_AUDIO = 1 << 2,
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_DATA = 1 << 3,
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_TRIGGER = 1 << 4,
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_FORM2 = 1 << 5,
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_RT = 1 << 6,
|
||||
PSX_CDROM_SECTOR_XA_SUBMODE_EOF = 1 << 7
|
||||
};
|
||||
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_MONO 0x00
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_STEREO 0x01
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_CHANNEL_MASK 0x03
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_FREQ_DOUBLE 0x00
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_FREQ_SINGLE 0x04
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_FREQ_MASK 0x0C
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_BITS_4 0x00
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_BITS_8 0x10
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_BITS_MASK 0x30
|
||||
#define PSX_CDROM_SECTOR_XA_CODING_EMPHASIS 0x40
|
||||
enum {
|
||||
PSX_CDROM_SECTOR_XA_CODING_MONO = 0 << 0,
|
||||
PSX_CDROM_SECTOR_XA_CODING_STEREO = 1 << 0,
|
||||
PSX_CDROM_SECTOR_XA_CODING_CHANNEL_MASK = 3 << 0,
|
||||
PSX_CDROM_SECTOR_XA_CODING_FREQ_DOUBLE = 0 << 2,
|
||||
PSX_CDROM_SECTOR_XA_CODING_FREQ_SINGLE = 1 << 2,
|
||||
PSX_CDROM_SECTOR_XA_CODING_FREQ_MASK = 3 << 2,
|
||||
PSX_CDROM_SECTOR_XA_CODING_BITS_4 = 0 << 4,
|
||||
PSX_CDROM_SECTOR_XA_CODING_BITS_8 = 1 << 4,
|
||||
PSX_CDROM_SECTOR_XA_CODING_BITS_MASK = 3 << 4,
|
||||
PSX_CDROM_SECTOR_XA_CODING_EMPHASIS = 1 << 6
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PSX_CDROM_SECTOR_TYPE_MODE1,
|
||||
|
Reference in New Issue
Block a user