Files
Yosuga/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppWavFileHandler.hpp
T
Misaki bb600bbbc4 first
2025-12-04 19:11:29 +08:00

235 lines
7.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Copyright(c) Live2D Inc. All rights reserved.
*
* Use of this source code is governed by the Live2D Open Software license
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
*/
#pragma once
#include <CubismFramework.hpp>
#include <Type/csmVector.hpp>
/**
* @brief wavファイルハンドラ
* @attention 16bit wav ファイル読み込みのみ実装済み
*/
class LAppWavFileHandler
{
public:
/**
* @brief 読み込んだwavfileの情報
*/
struct WavFileInfo
{
/**
* @brief コンストラクタ
*/
WavFileInfo() : _fileName(""), _numberOfChannels(0),
_bitsPerSample(0), _samplingRate(0), _samplesPerChannel(0),
_avgBytesPerSec(0), _blockAlign(0)
{ }
Csm::csmString _fileName; ///< ファイル名
Csm::csmUint32 _numberOfChannels; ///< チャンネル数
Csm::csmUint32 _bitsPerSample; ///< サンプルあたりビット数
Csm::csmUint32 _samplingRate; ///< サンプリングレート
Csm::csmUint32 _samplesPerChannel; ///< 1チャンネルあたり総サンプル数
Csm::csmUint32 _avgBytesPerSec; ///< 平均データ速度
Csm::csmUint32 _blockAlign; ///< ブロックサイズ
} _wavFileInfo;
/**
* @brief コンストラクタ
*/
LAppWavFileHandler();
/**
* @brief デストラクタ
*/
~LAppWavFileHandler();
/**
* @brief wavファイルハンドラの内部状態更新
*
* @param[in] deltaTimeSeconds デルタ時間[秒]
* @retval true 更新されている
* @retval false 更新されていない
*/
Csm::csmBool Update(Csm::csmFloat32 deltaTimeSeconds);
/**
* @brief 引数で指定したwavファイルの読み込みを開始する
*
* @param[in] filePath wavファイルのパス
*/
void Start(const Csm::csmString& filePath);
/**
* @brief 現在のRMS値取得
*
* @retval csmFloat32 RMS値
*/
Csm::csmFloat32 GetRms() const;
/**
* @brief ファイル情報を取得
*
* @retval ファイル情報
*/
const WavFileInfo& GetWavFileInfo() const;
/**
* @brief 正規化前のデータを取得
*
* @retval 正規化前のデータ
*/
const Csm::csmByte* GetRawData() const;
/**
* @brief 正規化前のデータの大きさを取得
*
* @retval 正規化前のデータの大きさ
*/
Csm::csmUint64 GetRawDataSize() const;
/**
* @brief 正規化データを取得する
*
* @retval 正規化データ
*/
Csm::csmVector<Csm::csmFloat32> GetPcmData() const;
/**
* @brief 引数で指定したチャンネルの正規化データを取得する
*
* @param[in] dst 格納先
* @param[in] useChannel 使用するチャンネル
*/
void GetPcmDataChannel(Csm::csmFloat32* dst, Csm::csmUint32 useChannel) const;
/**
* @brief -11の範囲の1サンプル取得
*
* @param[in] bitsPerSample ビット深度
* @param[in] data 正規化したいデータ
* @param[in] dataSize 正規化したいデータの大きさ
*
* @retval csmFloat32 正規化されたサンプル
*/
static Csm::csmFloat32 NormalizePcmSample(Csm::csmUint32 bitsPerSample, Csm::csmByte* data, Csm::csmUint32 dataSize);
private:
/**
* @brief wavファイルのロード
*
* @param[in] filePath wavファイルのパス
* @retval true 読み込み成功
* @retval false 読み込み失敗
*/
Csm::csmBool LoadWavFile(const Csm::csmString& filePath);
/**
* @brief PCMデータの解放
*/
void ReleasePcmData();
/**
* @brief -11の範囲の1サンプル取得
* @retval csmFloat32 正規化されたサンプル
*/
Csm::csmFloat32 GetPcmSample();
/**
* @brief バイトリーダ
*/
struct ByteReader {
/**
* @brief コンストラクタ
*/
ByteReader() : _fileByte(NULL), _fileSize(0), _readOffset(0)
{ }
/**
* @brief 8ビット読み込み
* @return Csm::csmUint8 読み取った8ビット値
*/
Csm::csmUint8 Get8()
{
const Csm::csmUint8 ret = _fileByte[_readOffset];
_readOffset++;
return ret;
}
/**
* @brief 16ビット読み込み(リトルエンディアン)
* @return Csm::csmUint16 読み取った16ビット値
*/
Csm::csmUint16 Get16LittleEndian()
{
const Csm::csmUint16 ret = (_fileByte[_readOffset + 1] << 8) | _fileByte[_readOffset];
_readOffset += 2;
return ret;
}
/**
* @brief 24ビット読み込み(リトルエンディアン)
* @return Csm::csmUint32 読み取った24ビット値(下位24ビットに設定)
*/
Csm::csmUint32 Get24LittleEndian()
{
const Csm::csmUint32 ret =
(_fileByte[_readOffset + 2] << 16) | (_fileByte[_readOffset + 1] << 8)
| _fileByte[_readOffset];
_readOffset += 3;
return ret;
}
/**
* @brief 32ビット読み込み(リトルエンディアン)
* @return Csm::csmUint32 読み取った32ビット値
*/
Csm::csmUint32 Get32LittleEndian()
{
const Csm::csmUint32 ret =
(_fileByte[_readOffset + 3] << 24) | (_fileByte[_readOffset + 2] << 16)
| (_fileByte[_readOffset + 1] << 8) | _fileByte[_readOffset];
_readOffset += 4;
return ret;
}
/**
* @brief シグネチャの取得と参照文字列との一致チェック
* @param[in] reference 検査対象のシグネチャ文字列
* @retval true 一致している
* @retval false 一致していない
*/
Csm::csmBool GetCheckSignature(const Csm::csmString& reference)
{
Csm::csmChar getSignature[4] = { 0, 0, 0, 0 };
const Csm::csmChar* referenceString = reference.GetRawString();
if (reference.GetLength() != 4)
{
return false;
}
for (Csm::csmUint32 signatureOffset = 0; signatureOffset < 4; signatureOffset++)
{
getSignature[signatureOffset] = static_cast<Csm::csmChar>(Get8());
}
return (getSignature[0] == referenceString[0]) && (getSignature[1] == referenceString[1])
&& (getSignature[2] == referenceString[2]) && (getSignature[3] == referenceString[3]);
}
Csm::csmByte* _fileByte; ///< ロードしたファイルのバイト列
Csm::csmSizeInt _fileSize; ///< ファイルサイズ
Csm::csmUint32 _readOffset; ///< ファイル参照位置
} _byteReader;
Csm::csmByte* _rawData; ///< 正規化される前のバイト列
Csm::csmUint64 _rawDataSize; ///< 正規化される前のバイト列の大きさ
Csm::csmFloat32** _pcmData; ///< -1から1の範囲で表現された音声データ配列
Csm::csmUint32 _sampleOffset; ///< サンプル参照位置
Csm::csmFloat32 _lastRms; ///< 最後に計測したRMS値
Csm::csmFloat32 _userTimeSeconds; ///< デルタ時間の積算値[秒]
};