123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- // Copyright 2008 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include "AudioCommon/WaveFile.h"
- #include <string>
- #include <fmt/format.h>
- #include "AudioCommon/Mixer.h"
- #include "Common/CommonTypes.h"
- #include "Common/FileUtil.h"
- #include "Common/IOFile.h"
- #include "Common/Logging/Log.h"
- #include "Common/MsgHandler.h"
- #include "Common/StringUtil.h"
- #include "Common/Swap.h"
- #include "Core/Config/MainSettings.h"
- #include "Core/ConfigManager.h"
- constexpr size_t WaveFileWriter::BUFFER_SIZE;
- WaveFileWriter::WaveFileWriter()
- {
- }
- WaveFileWriter::~WaveFileWriter()
- {
- Stop();
- }
- bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate_divisor)
- {
- // Ask to delete file
- if (File::Exists(filename))
- {
- if (Config::Get(Config::MAIN_DUMP_AUDIO_SILENT) ||
- AskYesNoFmtT("Delete the existing file '{0}'?", filename))
- {
- File::Delete(filename);
- }
- else
- {
- // Stop and cancel dumping the audio
- return false;
- }
- }
- // Check if the file is already open
- if (file)
- {
- PanicAlertFmtT("The file {0} was already open, the file header will not be written.", filename);
- return false;
- }
- file.Open(filename, "wb");
- if (!file)
- {
- PanicAlertFmtT(
- "The file {0} could not be opened for writing. Please check if it's already opened "
- "by another program.",
- filename);
- return false;
- }
- audio_size = 0;
- if (basename.empty())
- SplitPath(filename, nullptr, &basename, nullptr);
- current_sample_rate_divisor = sample_rate_divisor;
- // -----------------
- // Write file header
- // -----------------
- Write4("RIFF");
- Write(100 * 1000 * 1000); // write big value in case the file gets truncated
- Write4("WAVE");
- Write4("fmt ");
- Write(16); // size of fmt block
- Write(0x00020001); // two channels, uncompressed
- const u32 sample_rate = Mixer::FIXED_SAMPLE_RATE_DIVIDEND / sample_rate_divisor;
- Write(sample_rate);
- Write(sample_rate * 2 * 2); // two channels, 16bit
- Write(0x00100004);
- Write4("data");
- Write(100 * 1000 * 1000 - 32);
- // We are now at offset 44
- if (file.Tell() != 44)
- PanicAlertFmt("Wrong offset: {}", file.Tell());
- return true;
- }
- void WaveFileWriter::Stop()
- {
- file.Seek(4, File::SeekOrigin::Begin);
- Write(audio_size + 36);
- file.Seek(40, File::SeekOrigin::Begin);
- Write(audio_size);
- file.Close();
- }
- void WaveFileWriter::Write(u32 value)
- {
- file.WriteArray(&value, 1);
- }
- void WaveFileWriter::Write4(const char* ptr)
- {
- file.WriteBytes(ptr, 4);
- }
- void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count,
- u32 sample_rate_divisor, int l_volume, int r_volume)
- {
- if (!file)
- {
- ERROR_LOG_FMT(AUDIO, "WaveFileWriter - file not open.");
- return;
- }
- if (count * 2 > BUFFER_SIZE)
- {
- ERROR_LOG_FMT(AUDIO, "WaveFileWriter - buffer too small (count = {}).", count);
- return;
- }
- if (skip_silence)
- {
- bool all_zero = true;
- for (u32 i = 0; i < count * 2; i++)
- {
- if (sample_data[i])
- all_zero = false;
- }
- if (all_zero)
- return;
- }
- for (u32 i = 0; i < count; i++)
- {
- // Flip the audio channels from RL to LR
- conv_buffer[2 * i] = Common::swap16((u16)sample_data[2 * i + 1]);
- conv_buffer[2 * i + 1] = Common::swap16((u16)sample_data[2 * i]);
- // Apply volume (volume ranges from 0 to 256)
- conv_buffer[2 * i] = conv_buffer[2 * i] * l_volume / 256;
- conv_buffer[2 * i + 1] = conv_buffer[2 * i + 1] * r_volume / 256;
- }
- if (sample_rate_divisor != current_sample_rate_divisor)
- {
- Stop();
- file_index++;
- const std::string filename =
- fmt::format("{}{}{}.wav", File::GetUserPath(D_DUMPAUDIO_IDX), basename, file_index);
- Start(filename, sample_rate_divisor);
- current_sample_rate_divisor = sample_rate_divisor;
- }
- file.WriteBytes(conv_buffer.data(), count * 4);
- audio_size += count * 4;
- }
|