mirror of
https://github.com/JaCzekanski/Avocado.git
synced 2024-06-02 19:27:41 -04:00
cdrom: cd audio / xa mixing moved from SPU to CDROM
This commit is contained in:
parent
6cca4451c3
commit
8a10036c48
|
@ -67,18 +67,13 @@ void CDROM::step() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!this->mute) {
|
||||
if (!mute) {
|
||||
// Decode Red Book Audio (16bit Stereo 44100Hz)
|
||||
bool channel = true;
|
||||
for (size_t i = 0; i < rawSector.size(); i += 2) {
|
||||
int16_t sample = rawSector[i] | (rawSector[i + 1] << 8);
|
||||
for (size_t i = 0; i < rawSector.size(); i += 4) {
|
||||
int16_t left = rawSector[i + 0] | (rawSector[i + 1] << 8);
|
||||
int16_t right = rawSector[i + 2] | (rawSector[i + 3] << 8);
|
||||
|
||||
if (channel) {
|
||||
audio.first.push_back(sample);
|
||||
} else {
|
||||
audio.second.push_back(sample);
|
||||
}
|
||||
channel = !channel;
|
||||
audio.push_back(mixSample(std::make_pair(left, right)));
|
||||
}
|
||||
}
|
||||
} else if (trackType == disc::TrackType::DATA && stat.read) {
|
||||
|
@ -126,9 +121,11 @@ void CDROM::step() {
|
|||
}
|
||||
|
||||
if (this->mode.xaEnabled && !this->mute) {
|
||||
auto [left, right] = ADPCM::decodeXA(rawSector.data() + 24, codinginfo);
|
||||
audio.first.insert(audio.first.end(), left.begin(), left.end());
|
||||
audio.second.insert(audio.second.end(), right.begin(), right.end());
|
||||
auto frame = ADPCM::decodeXA(rawSector.data() + 24, codinginfo);
|
||||
|
||||
for (auto sample : frame) {
|
||||
audio.push_back(mixSample(sample));
|
||||
}
|
||||
}
|
||||
|
||||
if (submode.endOfFile) {
|
||||
|
@ -374,5 +371,26 @@ void CDROM::write(uint32_t address, uint8_t data) {
|
|||
|
||||
fmt::print("CDROM{}.{}<-W UNIMPLEMENTED WRITE 0x{:02x}\n", address, static_cast<int>(status.index), data);
|
||||
}
|
||||
|
||||
std::pair<int16_t, int16_t> CDROM::mixSample(std::pair<int16_t, int16_t> input) {
|
||||
int16_t left = input.first;
|
||||
int16_t right = input.second;
|
||||
|
||||
// TODO: Fixed-point + clipping
|
||||
// TODO: Verify mixing with HW (capture channels)
|
||||
// 0x00 - disabled
|
||||
// 0x80 - 1x vol
|
||||
// 0xff - 2x vol
|
||||
float l_l = volumeLeftToLeft / (float)0x80;
|
||||
float l_r = volumeLeftToRight / (float)0x80;
|
||||
float r_l = volumeRightToLeft / (float)0x80;
|
||||
float r_r = volumeRightToRight / (float)0x80;
|
||||
|
||||
int16_t mixedLeft = clamp<int32_t>((left * l_l) + (right * r_l), INT16_MIN, INT16_MAX);
|
||||
int16_t mixedRight = clamp<int32_t>((left * l_r) + (right * r_r), INT16_MIN, INT16_MAX);
|
||||
|
||||
return std::make_pair(mixedLeft, mixedRight);
|
||||
}
|
||||
|
||||
} // namespace cdrom
|
||||
} // namespace device
|
||||
|
|
|
@ -114,6 +114,10 @@ class CDROM {
|
|||
|
||||
Mode mode;
|
||||
Filter filter;
|
||||
uint8_t volumeLeftToLeft = 0;
|
||||
uint8_t volumeLeftToRight = 0;
|
||||
uint8_t volumeRightToLeft = 0;
|
||||
uint8_t volumeRightToRight = 0;
|
||||
|
||||
System* sys;
|
||||
int readSector = 0;
|
||||
|
@ -174,13 +178,10 @@ class CDROM {
|
|||
}
|
||||
|
||||
std::string dumpFifo(const FIFO& f);
|
||||
std::pair<int16_t, int16_t> mixSample(std::pair<int16_t, int16_t> sample);
|
||||
|
||||
public:
|
||||
uint8_t volumeLeftToLeft = 0;
|
||||
uint8_t volumeLeftToRight = 0;
|
||||
uint8_t volumeRightToLeft = 0;
|
||||
uint8_t volumeRightToRight = 0;
|
||||
std::pair<std::deque<int16_t>, std::deque<int16_t>> audio;
|
||||
std::deque<std::pair<int16_t, int16_t>> audio;
|
||||
std::vector<uint8_t> rawSector;
|
||||
|
||||
std::vector<uint8_t> dataBuffer;
|
||||
|
|
|
@ -381,8 +381,7 @@ void CDROM::cmdGetId() {
|
|||
void CDROM::cmdReadS() {
|
||||
readSector = seekSector;
|
||||
|
||||
audio.first.clear();
|
||||
audio.second.clear();
|
||||
audio.clear();
|
||||
stat.setMode(StatusCode::Mode::Reading);
|
||||
|
||||
postInterrupt(3);
|
||||
|
|
|
@ -87,8 +87,24 @@ void SPU::step(device::cdrom::CDROM* cdrom) {
|
|||
}
|
||||
}
|
||||
|
||||
sumLeft *= mainVolume.getLeft();
|
||||
sumRight *= mainVolume.getRight();
|
||||
// Mix with cd
|
||||
Sample cdLeft = 0, cdRight = 0;
|
||||
if (!cdrom->audio.empty()) {
|
||||
std::tie(cdLeft, cdRight) = cdrom->audio.front();
|
||||
|
||||
// TODO: Refactor to use ring buffer
|
||||
cdrom->audio.pop_front();
|
||||
|
||||
if (control.cdEnable) {
|
||||
sumLeft += cdLeft * cdVolume.getLeft();
|
||||
sumRight += cdRight * cdVolume.getRight();
|
||||
|
||||
if (control.cdReverb) {
|
||||
sumReverbLeft += cdLeft * cdVolume.getLeft();
|
||||
sumReverbRight += cdRight * cdVolume.getRight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!forceReverbOff && control.masterReverb) {
|
||||
static int16_t reverbLeft = 0, reverbRight = 0;
|
||||
|
@ -100,37 +116,14 @@ void SPU::step(device::cdrom::CDROM* cdrom) {
|
|||
sumRight += reverbRight;
|
||||
}
|
||||
|
||||
sumLeft *= std::min<int16_t>(0x3fff, mainVolume.getLeft()) * 2;
|
||||
sumRight *= std::min<int16_t>(0x3fff, mainVolume.getRight()) * 2;
|
||||
|
||||
if (!control.unmute) {
|
||||
sumLeft = 0;
|
||||
sumRight = 0;
|
||||
}
|
||||
|
||||
// Mix with cd
|
||||
int16_t cdLeft = 0, cdRight = 0;
|
||||
if (!cdrom->audio.first.empty()) {
|
||||
cdLeft = cdrom->audio.first.front();
|
||||
cdRight = cdrom->audio.second.front();
|
||||
|
||||
// TODO: Refactor to use ring buffer
|
||||
cdrom->audio.first.pop_front();
|
||||
cdrom->audio.second.pop_front();
|
||||
|
||||
if (control.cdEnable) {
|
||||
// 0x80 - full volume
|
||||
// 0xff - 2x volume
|
||||
int32_t l_l = 255 * cdrom->volumeLeftToLeft;
|
||||
int32_t l_r = 255 * cdrom->volumeLeftToRight;
|
||||
int32_t r_l = 255 * cdrom->volumeRightToLeft;
|
||||
int32_t r_r = 255 * cdrom->volumeRightToRight;
|
||||
|
||||
sumLeft += (cdLeft * l_l) >> 15;
|
||||
sumRight += (cdLeft * l_r) >> 15;
|
||||
|
||||
sumLeft += (cdLeft * r_l) >> 15;
|
||||
sumRight += (cdLeft * r_r) >> 15;
|
||||
}
|
||||
}
|
||||
|
||||
audioBuffer[audioBufferPos] = sumLeft;
|
||||
audioBuffer[audioBufferPos + 1] = sumRight;
|
||||
|
||||
|
|
|
@ -148,12 +148,11 @@ std::vector<int16_t> decodePacket(uint8_t buffer[128], int32_t prevSample[2], bo
|
|||
return decoded;
|
||||
}
|
||||
|
||||
std::pair<std::vector<int16_t>, std::vector<int16_t>> decodeXA(uint8_t buffer[128 * 18], cd::Codinginfo codinginfo) {
|
||||
std::vector<std::pair<int16_t, int16_t>> decodeXA(uint8_t buffer[128 * 18], cd::Codinginfo codinginfo) {
|
||||
static int32_t prevSampleLeft[2] = {};
|
||||
static int32_t prevSampleRight[2] = {};
|
||||
|
||||
std::vector<int16_t> left;
|
||||
std::vector<int16_t> right;
|
||||
std::vector<std::pair<int16_t, int16_t>> frame;
|
||||
|
||||
// Each sector contains of 18 128-byte portions
|
||||
for (int packet = 0; packet < 18; packet++) {
|
||||
|
@ -161,15 +160,17 @@ std::pair<std::vector<int16_t>, std::vector<int16_t>> decodeXA(uint8_t buffer[12
|
|||
auto l = decodePacket<Channel::left>(buffer + packet * 128, prevSampleLeft, codinginfo.sampleRate);
|
||||
auto r = decodePacket<Channel::right>(buffer + packet * 128, prevSampleRight, codinginfo.sampleRate);
|
||||
|
||||
left.insert(left.end(), l.begin(), l.end());
|
||||
right.insert(right.end(), r.begin(), r.end());
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
frame.emplace_back(l[i], r[i]);
|
||||
}
|
||||
} else {
|
||||
auto mono = decodePacket<Channel::mono>(buffer + packet * 128, prevSampleLeft, codinginfo.sampleRate);
|
||||
left.insert(left.end(), mono.begin(), mono.end());
|
||||
right.insert(right.end(), mono.begin(), mono.end());
|
||||
for (auto sample : mono) {
|
||||
frame.emplace_back(sample, sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(left, right);
|
||||
return frame;
|
||||
}
|
||||
} // namespace ADPCM
|
||||
|
|
|
@ -18,5 +18,5 @@ enum Flag {
|
|||
// 0 - Nothing
|
||||
};
|
||||
std::vector<int16_t> decode(uint8_t buffer[16], int32_t prevSample[2]);
|
||||
std::pair<std::vector<int16_t>, std::vector<int16_t>> decodeXA(uint8_t buffer[128 * 18], cd::Codinginfo codinginfo);
|
||||
std::vector<std::pair<int16_t, int16_t>> decodeXA(uint8_t buffer[128 * 18], cd::Codinginfo codinginfo);
|
||||
}; // namespace ADPCM
|
Loading…
Reference in a new issue