mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add support for 8-bit and mono WAV files. More fixes.
This commit is contained in:
parent
18fbe7afe8
commit
de20a5692f
3 changed files with 45 additions and 15 deletions
|
@ -369,6 +369,11 @@ void BackgroundAudio::Update() {
|
|||
}
|
||||
}
|
||||
|
||||
inline int16_t ConvertU8ToI16(uint8_t value) {
|
||||
int ivalue = value - 128;
|
||||
return ivalue * 255;
|
||||
}
|
||||
|
||||
Sample *Sample::Load(const std::string &path) {
|
||||
size_t bytes;
|
||||
uint8_t *data = g_VFS.ReadFile(path.c_str(), &bytes);
|
||||
|
@ -384,14 +389,22 @@ Sample *Sample::Load(const std::string &path) {
|
|||
|
||||
delete[] data;
|
||||
|
||||
if (wave.num_channels != 2 || wave.raw_bytes_per_frame != 4) {
|
||||
ERROR_LOG(AUDIO, "Wave format not supported for mixer playback. Must be 16-bit raw stereo. '%s'", path.c_str());
|
||||
if (wave.num_channels > 2 || wave.raw_bytes_per_frame > sizeof(int16_t) * wave.num_channels) {
|
||||
ERROR_LOG(AUDIO, "Wave format not supported for mixer playback. Must be 8-bit or 16-bit raw mono or stereo. '%s'", path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int16_t *samples = new int16_t[2 * wave.numFrames];
|
||||
memcpy(samples, wave.raw_data, wave.numFrames * wave.raw_bytes_per_frame);
|
||||
return new Sample(samples, wave.numFrames, wave.sample_rate);
|
||||
int16_t *samples = new int16_t[wave.num_channels * wave.numFrames];
|
||||
if (wave.raw_bytes_per_frame == wave.num_channels * 2) {
|
||||
// 16-bit
|
||||
memcpy(samples, wave.raw_data, wave.numFrames * wave.raw_bytes_per_frame);
|
||||
} else if (wave.raw_bytes_per_frame == wave.num_channels) {
|
||||
// 8-bit. Convert.
|
||||
for (int i = 0; i < wave.num_channels * wave.numFrames; i++) {
|
||||
samples[i] = ConvertU8ToI16(wave.raw_data[i]);
|
||||
}
|
||||
}
|
||||
return new Sample(samples, wave.num_channels, wave.numFrames, wave.sample_rate);
|
||||
}
|
||||
|
||||
static inline int16_t Clamp16(int32_t sample) {
|
||||
|
@ -434,15 +447,25 @@ void SoundEffectMixer::Mix(int16_t *buffer, int sz, int sampleRateHz) {
|
|||
int wholeOffset = iter->offset >> 32;
|
||||
int frac = (iter->offset >> 20) & 0xFFF; // Use a 12 bit fraction to get away with 32-bit multiplies
|
||||
|
||||
int interpolatedLeft = (sample->data_[wholeOffset * 2] * (0x1000 - frac) + sample->data_[(wholeOffset + 1) * 2] * frac) >> 12;
|
||||
int interpolatedRight = (sample->data_[wholeOffset * 2 + 1] * (0x1000 - frac) + sample->data_[(wholeOffset + 1) * 2 + 1] * frac) >> 12;
|
||||
if (sample->channels_ == 2) {
|
||||
int interpolatedLeft = (sample->data_[wholeOffset * 2] * (0x1000 - frac) + sample->data_[(wholeOffset + 1) * 2] * frac) >> 12;
|
||||
int interpolatedRight = (sample->data_[wholeOffset * 2 + 1] * (0x1000 - frac) + sample->data_[(wholeOffset + 1) * 2 + 1] * frac) >> 12;
|
||||
|
||||
// Clamping add on top per sample. Not great, we should be mixing at higher bitrate instead. Oh well.
|
||||
int left = Clamp16(buffer[i] + (interpolatedLeft * iter->volume >> 8));
|
||||
int right = Clamp16(buffer[i + 1] + (interpolatedRight * iter->volume >> 8));
|
||||
// Clamping add on top per sample. Not great, we should be mixing at higher bitrate instead. Oh well.
|
||||
int left = Clamp16(buffer[i] + (interpolatedLeft * iter->volume >> 8));
|
||||
int right = Clamp16(buffer[i + 1] + (interpolatedRight * iter->volume >> 8));
|
||||
|
||||
buffer[i] = left;
|
||||
buffer[i + 1] = right;
|
||||
buffer[i] = left;
|
||||
buffer[i + 1] = right;
|
||||
} else if (sample->channels_ == 1) {
|
||||
int interpolated = (sample->data_[wholeOffset] * (0x1000 - frac) + sample->data_[wholeOffset + 1] * frac) >> 12;
|
||||
|
||||
// Clamping add on top per sample. Not great, we should be mixing at higher bitrate instead. Oh well.
|
||||
int value = Clamp16(buffer[i] + (interpolated * iter->volume >> 8));
|
||||
|
||||
buffer[i] = value;
|
||||
buffer[i + 1] = value;
|
||||
}
|
||||
|
||||
iter->offset += stride;
|
||||
}
|
||||
|
@ -462,6 +485,7 @@ void SoundEffectMixer::Play(UI::UISound sfx, float volume) {
|
|||
|
||||
void SoundEffectMixer::UpdateSample(UI::UISound sound, Sample *sample) {
|
||||
if (sample) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
samples_[(size_t)sound] = std::unique_ptr<Sample>(sample);
|
||||
} else {
|
||||
LoadDefaultSample(sound);
|
||||
|
@ -485,6 +509,7 @@ void SoundEffectMixer::LoadDefaultSample(UI::UISound sound) {
|
|||
if (!sample) {
|
||||
ERROR_LOG(SYSTEM, "Failed to load the default sample for UI sound %d", (int)sound);
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
samples_[(size_t)sound] = std::unique_ptr<Sample>(sample);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,14 @@ class AT3PlusReader;
|
|||
|
||||
struct Sample {
|
||||
// data must be new-ed.
|
||||
Sample(int16_t *data, int length, int rateInHz) : data_(data), length_(length), rateInHz_(rateInHz) {}
|
||||
Sample(int16_t *data, int channels, int length, int rateInHz) : channels_(channels), data_(data), length_(length), rateInHz_(rateInHz) {}
|
||||
~Sample() {
|
||||
delete[] data_;
|
||||
}
|
||||
int16_t *data_;
|
||||
int length_; // stereo samples.
|
||||
int length_; // stereo or mono samples.
|
||||
int rateInHz_; // sampleRate
|
||||
int channels_;
|
||||
|
||||
static Sample *Load(const std::string &path);
|
||||
};
|
||||
|
|
|
@ -54,6 +54,7 @@ AudioFileChooser::AudioFileChooser(std::string *value, const std::string &title,
|
|||
return UI::EVENT_DONE;
|
||||
});
|
||||
Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(ITEM_HEIGHT, ITEM_HEIGHT)))->OnClick.Add([=](UI::EventParams &) {
|
||||
g_BackgroundAudio.SFX().UpdateSample(sound, nullptr);
|
||||
value->clear();
|
||||
return UI::EVENT_DONE;
|
||||
});
|
||||
|
@ -239,7 +240,10 @@ void RetroAchievementsSettingsScreen::CreateTabs() {
|
|||
using namespace UI;
|
||||
|
||||
CreateAccountTab(AddTab("AchievementsAccount", ac->T("Account")));
|
||||
CreateCustomizeTab(AddTab("AchievementsCustomize", ac->T("Customize")));
|
||||
if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) {
|
||||
// Don't bother creating this tab if we don't have a file browser.
|
||||
CreateCustomizeTab(AddTab("AchievementsCustomize", ac->T("Customize")));
|
||||
}
|
||||
CreateDeveloperToolsTab(AddTab("AchievementsDeveloperTools", sy->T("Developer Tools")));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue