|
|
|
|
@ -4,8 +4,10 @@
|
|
|
|
|
#include <cmath> |
|
|
|
|
#include <utility> |
|
|
|
|
|
|
|
|
|
#ifndef PS2 |
|
|
|
|
#include <Aulib/DecoderDrmp3.h> |
|
|
|
|
#include <Aulib/DecoderDrwav.h> |
|
|
|
|
#endif |
|
|
|
|
#include <SDL.h> |
|
|
|
|
#ifdef USE_SDL1 |
|
|
|
|
#include "utils/sdl2_to_1_2_backports.h" |
|
|
|
|
@ -15,7 +17,9 @@
|
|
|
|
|
|
|
|
|
|
#include "engine/assets.hpp" |
|
|
|
|
#include "options.h" |
|
|
|
|
#ifndef PS2 |
|
|
|
|
#include "utils/aulib.hpp" |
|
|
|
|
#endif |
|
|
|
|
#include "utils/log.hpp" |
|
|
|
|
#include "utils/math.h" |
|
|
|
|
#include "utils/stubs.h" |
|
|
|
|
@ -57,6 +61,7 @@ float PanLogToLinear(int logPan)
|
|
|
|
|
return copysign(1.F - factor, static_cast<float>(logPan)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef PS2 |
|
|
|
|
std::unique_ptr<Aulib::Decoder> CreateDecoder(bool isMp3) |
|
|
|
|
{ |
|
|
|
|
if (isMp3) |
|
|
|
|
@ -72,6 +77,7 @@ std::unique_ptr<Aulib::Stream> CreateStream(SDL_RWops *handle, bool isMp3)
|
|
|
|
|
auto resampler = CreateAulibResampler(decoder->getRate()); |
|
|
|
|
return std::make_unique<Aulib::Stream>(handle, std::move(decoder), std::move(resampler), /*closeRw=*/true); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Converts log volume passed in into linear volume. |
|
|
|
|
@ -92,9 +98,15 @@ float VolumeLogToLinear(int logVolume, int logMin, int logMax)
|
|
|
|
|
|
|
|
|
|
void SoundSample::Release() |
|
|
|
|
{ |
|
|
|
|
stream_ = nullptr; |
|
|
|
|
#ifndef PS2 |
|
|
|
|
file_data_ = nullptr; |
|
|
|
|
file_data_size_ = 0; |
|
|
|
|
#else |
|
|
|
|
if (stream_ != nullptr) // We are the owner
|
|
|
|
|
audsrv_free_adpcm(sampleId_); |
|
|
|
|
sampleId_ = nullptr; |
|
|
|
|
#endif |
|
|
|
|
stream_ = nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -102,15 +114,37 @@ void SoundSample::Release()
|
|
|
|
|
*/ |
|
|
|
|
bool SoundSample::IsPlaying() |
|
|
|
|
{ |
|
|
|
|
#ifndef PS2 |
|
|
|
|
return stream_ && stream_->isPlaying(); |
|
|
|
|
#else |
|
|
|
|
if (channel_ == -1) |
|
|
|
|
return false; |
|
|
|
|
return audsrv_is_adpcm_playing(channel_, sampleId_) != 0; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool SoundSample::Play(int numIterations) |
|
|
|
|
{ |
|
|
|
|
#ifndef PS2 |
|
|
|
|
if (!stream_->play(numIterations)) { |
|
|
|
|
LogError(LogCategory::Audio, "Aulib::Stream::play (from SoundSample::Play): {}", SDL_GetError()); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
if (IsStreaming()) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int channel = audsrv_ch_play_adpcm(-1, sampleId_); |
|
|
|
|
printf("channel %d\n", channel); |
|
|
|
|
if (channel < 0) { |
|
|
|
|
LogError(LogCategory::Audio, "audsrv_ch_play_adpcm (from SoundSample::Play): {}", channel); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
channel_ = channel; |
|
|
|
|
|
|
|
|
|
audsrv_adpcm_set_volume_and_pan(channel_, volume_, pan_); |
|
|
|
|
#endif |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -123,6 +157,7 @@ int SoundSample::SetChunkStream(std::string filePath, bool isMp3, bool logErrors
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
file_path_ = std::move(filePath); |
|
|
|
|
#ifndef PS2 |
|
|
|
|
isMp3_ = isMp3; |
|
|
|
|
stream_ = CreateStream(handle, isMp3); |
|
|
|
|
if (!stream_->open()) { |
|
|
|
|
@ -131,11 +166,13 @@ int SoundSample::SetChunkStream(std::string filePath, bool isMp3, bool logErrors
|
|
|
|
|
LogError(LogCategory::Audio, "Aulib::Stream::open (from SoundSample::SetChunkStream) for {}: {}", file_path_, SDL_GetError()); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int SoundSample::SetChunk(ArraySharedPtr<std::uint8_t> fileData, std::size_t dwBytes, bool isMp3) |
|
|
|
|
{ |
|
|
|
|
#ifndef PS2 |
|
|
|
|
isMp3_ = isMp3; |
|
|
|
|
file_data_ = std::move(fileData); |
|
|
|
|
file_data_size_ = dwBytes; |
|
|
|
|
@ -151,25 +188,76 @@ int SoundSample::SetChunk(ArraySharedPtr<std::uint8_t> fileData, std::size_t dwB
|
|
|
|
|
LogError(LogCategory::Audio, "Aulib::Stream::open (from SoundSample::SetChunk): {}", SDL_GetError()); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
stream_ = std::make_unique<audsrv_adpcm_t>(); |
|
|
|
|
int success = audsrv_load_adpcm(stream_.get(), fileData.get(), dwBytes); |
|
|
|
|
if (success != 0) { |
|
|
|
|
LogError(LogCategory::Audio, "audsrv_load_adpcm (from SoundSample::SetChunk): {}", success); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
sampleId_ = stream_.get(); |
|
|
|
|
#endif |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SoundSample::SetVolume(int logVolume, int logMin, int logMax) |
|
|
|
|
{ |
|
|
|
|
#ifndef PS2 |
|
|
|
|
stream_->setVolume(VolumeLogToLinear(logVolume, logMin, logMax)); |
|
|
|
|
#else |
|
|
|
|
volume_ = VolumeLogToLinear(logVolume, logMin, logMax) * MAX_VOLUME; |
|
|
|
|
if (channel_ == -1) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
audsrv_adpcm_set_volume_and_pan(channel_, volume_, pan_); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SoundSample::SetStereoPosition(int logPan) |
|
|
|
|
{ |
|
|
|
|
#ifndef PS2 |
|
|
|
|
stream_->setStereoPosition(PanLogToLinear(logPan)); |
|
|
|
|
#else |
|
|
|
|
pan_ = PanLogToLinear(logPan) * 100; |
|
|
|
|
if (channel_ == -1) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
audsrv_adpcm_set_volume_and_pan(channel_, volume_, pan_); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int SoundSample::GetLength() const |
|
|
|
|
{ |
|
|
|
|
#ifndef PS2 |
|
|
|
|
if (!stream_) |
|
|
|
|
return 0; |
|
|
|
|
return std::chrono::duration_cast<std::chrono::milliseconds>(stream_->duration()).count(); |
|
|
|
|
#else |
|
|
|
|
size_t size = 0; |
|
|
|
|
int pitch = 0; |
|
|
|
|
|
|
|
|
|
if (stream_ != nullptr) { |
|
|
|
|
size = stream_->size; |
|
|
|
|
pitch = stream_->pitch; |
|
|
|
|
} else if (!file_path_.empty()) { |
|
|
|
|
AssetHandle handle = OpenAsset(file_path_.c_str(), size); |
|
|
|
|
if (handle.ok()) { |
|
|
|
|
size -= 16; |
|
|
|
|
uint32_t buffer[3]; |
|
|
|
|
if (handle.read(buffer, sizeof(buffer))) { |
|
|
|
|
pitch = buffer[2]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (pitch == 0) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
uint64_t microSamples = size; |
|
|
|
|
microSamples *= 56 * 1000; |
|
|
|
|
|
|
|
|
|
return microSamples / (pitch * 375); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace devilution
|
|
|
|
|
|