#include "ehs/io/audio/Audio.h" #include "ehs/io/File.h" #include "ehs/io/RIFF.h" namespace ehs { Array Audio::codecs; bool Audio::HasCodec(const UInt_64 hashExt) { for (UInt_64 i = 0; i < codecs.Size(); ++i) if (codecs[i].GetHashExt() == hashExt) return true; return false; } bool Audio::HasCodec(const Str_8& ext) { return HasCodec(ext.Hash_64()); } bool Audio::AddCodec(AudioCodec codec) { if (HasCodec(codec.GetHashExt())) return false; codecs.Push(std::move(codec)); return true; } const AudioCodec* Audio::GetCodec(const UInt_64 hashExt) { for (UInt_64 i = 0; i < codecs.Size(); ++i) if (codecs[i].GetHashExt() == hashExt) return &codecs[i]; return nullptr; } const AudioCodec* Audio::GetCodec(const Str_8& ext) { return GetCodec(ext.Hash_64()); } Audio::~Audio() { delete[] data; delete[] peak; } Audio::Audio() : sampleRate(0), dataType(DataType::FLOAT), byteDepth(0), channels(0), frames(0), length(0.0f), data(nullptr), peak(nullptr) { AddType("Audio"); } Audio::Audio(const Str_8& filePath) : Resource(File::ParseName_8(filePath)), sampleRate(0), dataType(DataType::FLOAT), byteDepth(0), channels(0), frames(0), length(0.0f), data(nullptr), peak(nullptr) { AddType("Audio"); File file(filePath, Mode::READ, Disposition::OPEN); Str_8 ext = file.GetExtension(); const AudioCodec* codec = GetCodec(ext); if (!codec) { EHS_LOG_INT(LogType::ERR, 0, "Codec not found for file extension, \"" + ext + "\"."); return; } Serializer data = file.ReadSerializer_64(codec->GetEndianness(), file.Size()); file.Release(); codec->Decode(data, this); } Audio::Audio(const Str_8& filePath, DataType type) : Resource(File::ParseName_8(filePath)), sampleRate(0), dataType(DataType::FLOAT), byteDepth(0), channels(0), frames(0), length(0.0f), data(nullptr), peak(nullptr) { AddType("Audio"); File file(filePath, Mode::READ, Disposition::OPEN); Str_8 ext = file.GetExtension(); const AudioCodec* codec = GetCodec(ext); if (!codec) { EHS_LOG_INT(LogType::ERR, 0, "Codec not found for file extension, \"" + ext + "\"."); return; } Serializer data = file.ReadSerializer_64(codec->GetEndianness(), file.Size()); file.Release(); codec->Decode(data, this); ToDataType(type); } Audio::Audio(Str_8 id, const UInt_64 sampleRate, const DataType dataType, const UInt_8 channels, const UInt_64 frames, const Byte* const data) : Resource((Str_8&&)id), dataType(dataType), byteDepth(ToByteDepth(dataType)), sampleRate(sampleRate), channels(channels), frames(frames), length((float)frames / (float)sampleRate), data(new Byte[GetSize()]), peak(new Byte[byteDepth]) { Util::Copy(this->data, data, GetSize()); AddType("Audio"); } Audio::Audio(Str_8 id, const UInt_64 sampleRate, const DataType dataType, const UInt_8 channels, const Serializer& data) : Resource((Str_8&&)id), sampleRate(sampleRate), dataType(dataType), byteDepth(ToByteDepth(dataType)), channels(channels), frames(data.Size() / channels / byteDepth), length((float)frames / (float)sampleRate), data(new Byte[data.Size()]), peak(new Byte[byteDepth]) { Util::Copy(this->data, data, data.Size()); AddType("Audio"); } Audio::Audio(Str_8 id, const UInt_64 sampleRate, const DataType dataType, const UInt_8 channels, const Vector& data) : Resource((Str_8&&)id), sampleRate(sampleRate), dataType(dataType), byteDepth(ToByteDepth(dataType)), channels(channels), frames(data.Size() / channels / byteDepth), length((float)frames / (float)sampleRate), data(new Byte[data.Size()]), peak(new Byte[byteDepth]) { Util::Copy(this->data, data, data.Size()); AddType("Audio"); } Audio::Audio(Str_8 id, const UInt_64 sampleRate, const DataType dataType, const UInt_8 channels, const Array& data) : Resource((Str_8&&)id), sampleRate(sampleRate), dataType(dataType), byteDepth(ToByteDepth(dataType)), channels(channels), frames(data.Size() / channels / byteDepth), length((float)frames / (float)sampleRate), data(new Byte[data.Size()]), peak(new Byte[byteDepth]) { Util::Copy(this->data, data, data.Size()); AddType("Audio"); } Audio::Audio(Str_8 id, const UInt_64 sampleRate, const DataType dataType, const UInt_8 channels, const UInt_64 frames) : Resource((Str_8&&)id), sampleRate(sampleRate), dataType(dataType), byteDepth(ToByteDepth(dataType)), channels(channels), frames(frames), length((float)frames / (float)sampleRate), data(new Byte[GetSize()]), peak(new Byte[byteDepth]) { AddType("Audio"); } Audio::Audio(Audio&& audio) noexcept : Resource((Resource&&)audio), sampleRate(audio.sampleRate), dataType(audio.dataType), byteDepth(audio.byteDepth), channels(audio.channels), frames(audio.frames), length(audio.length), data(audio.data), peak(audio.peak) { audio.sampleRate = 0; audio.dataType = DataType::FLOAT; audio.byteDepth = ToByteDepth(audio.dataType); audio.channels = 0; audio.frames = 0; audio.length = 0.0f; audio.data = nullptr; audio.peak = nullptr; } Audio::Audio(const Audio& audio) : Resource(audio), sampleRate(audio.sampleRate), dataType(audio.dataType), byteDepth(audio.byteDepth), channels(audio.channels), frames(audio.frames), length(audio.length), data(new Byte[GetSize()]), peak(new Byte[audio.byteDepth]) { Util::Copy(data, audio.data, GetSize()); } Audio& Audio::operator=(Audio&& audio) noexcept { if (this == &audio) return *this; Resource::operator=((Resource&&)audio); sampleRate = audio.sampleRate; dataType = audio.dataType; byteDepth = audio.byteDepth; channels = audio.channels; frames = audio.frames; length = audio.length; delete[] data; data = audio.data; delete[] peak; peak = audio.peak; audio.sampleRate = 0; audio.dataType = DataType::FLOAT; audio.byteDepth = ToByteDepth(audio.dataType); audio.channels = 0; audio.frames = 0; audio.length = 0.0f; audio.data = nullptr; audio.peak = nullptr; return *this; } Audio& Audio::operator=(const Audio& audio) { if (this == &audio) return *this; Resource::operator=(audio); sampleRate = audio.sampleRate; dataType = audio.dataType; byteDepth = audio.byteDepth; channels = audio.channels; length = audio.length; frames = audio.frames; delete[] data; data = new Byte[audio.GetSize()]; Util::Copy(data, audio.data, audio.GetSize()); delete[] peak; peak = new Byte[audio.byteDepth]; Util::Copy(peak, audio.peak, audio.byteDepth); return *this; } Audio::operator const Byte*() const { return data; } Audio::operator Byte*() { return data; } void Audio::Release() { sampleRate = 0; dataType = DataType::FLOAT; byteDepth = 0; channels = 0; frames = 0; length = 0.0f; delete[] data; data = nullptr; delete[] peak; peak = nullptr; } UInt_64 Audio::GetSampleRate() const { return sampleRate; } DataType Audio::GetDataType() const { return dataType; } UInt_8 Audio::GetByteDepth() const { return byteDepth; } UInt_8 Audio::GetBitDepth() const { return byteDepth * 8; } UInt_8 Audio::GetChannels() const { return channels; } UInt_64 Audio::GetFrameCount() const { return frames; } UInt_64 Audio::GetSampleCount() const { return channels * frames; } UInt_8 Audio::GetFrameSize() const { return byteDepth * channels; } UInt_64 Audio::GetSize() const { return byteDepth * channels * frames; } float Audio::GetLength() const { return length; } Byte* Audio::GetFrame(UInt_64 frameIndex) const { return &data[frameIndex * GetFrameSize()]; } Array Audio::FrameAsMono(const UInt_64 frameIndex) const { Array result(byteDepth); ToMono(1, result, frameIndex); return result; } Array Audio::FrameAsStereo(const UInt_64 frameIndex) const { Array result; if (channels == 1) { result.Resize(byteDepth * channels); Mono_to_Stereo(1, result, frameIndex); } else if (channels == 2) { return {&data[byteDepth * channels * frameIndex], (UInt_64)(byteDepth * channels)}; } else if (channels == 6) { result.Resize(byteDepth * channels); Five_One_to_Stereo(1, result, frameIndex); } else if (channels == 8) { result.Resize(byteDepth * channels); Seven_One_to_Stereo(1, result, frameIndex); } else { EHS_LOG_INT(LogType::ERR, 0, "Conversion from " + Str_8::FromNum(channels) + " channels, to 2 channels is unsupported."); } return result; } Array Audio::FrameAsFive_One(const UInt_64 frameIndex) const { Array result; if (channels == 1) { result.Resize(byteDepth * 6 ); Mono_to_Five_One(1, result, frameIndex); } else if (channels == 2) { result.Resize(byteDepth * 6); Stereo_to_Five_One(1, result, frameIndex); } else if (channels == 6) { return {&data[byteDepth * channels * frameIndex], (UInt_64)(byteDepth * channels)}; } else if (channels == 8) { result.Resize(byteDepth * 6); Seven_One_to_Five_One(1, result, frameIndex); } else { EHS_LOG_INT(LogType::ERR, 0, "Conversion from " + Str_8::FromNum(channels) + " channels, to 6 channels is unsupported."); } return result; } Array Audio::FrameAsSeven_One(const UInt_64 frameIndex) const { Array result; if (channels == 1) { result.Resize(byteDepth * 8); Mono_to_Seven_One(1, result, frameIndex); } else if (channels == 2) { result.Resize(byteDepth * 8); Stereo_to_Seven_One(1, result, frameIndex); } else if (channels == 6) { result.Resize(byteDepth * 8); Five_One_to_Seven_One(1, result, frameIndex); } else if (channels == 8) { return {&data[byteDepth * channels * frameIndex], (UInt_64)(byteDepth * channels)}; } else { EHS_LOG_INT(LogType::ERR, 0, "Conversion from " + Str_8::FromNum(channels) + " channels, to 8 channels is unsupported."); } return result; } SInt_8 Audio::SampleAsSInt_8(const UInt_64 sampleIndex) const { switch (dataType) { case DataType::SINT_8: return ((SInt_8 *)data)[sampleIndex]; case DataType::SINT_16: return (SInt_8)((double)((SInt_16 *)data)[sampleIndex] / (double)EHS_SINT_16_MAX * (double)EHS_SINT_8_MAX); case DataType::FLOAT: return (SInt_8)(((double *)data)[sampleIndex] * (double)EHS_SINT_8_MAX); case DataType::SINT_32: return (SInt_8)((double)((SInt_32 *)data)[sampleIndex] / (double)EHS_SINT_32_MAX * (double)EHS_SINT_8_MAX); case DataType::SINT_64: return (SInt_8)((double)((SInt_64 *)data)[sampleIndex] / (double)EHS_SINT_64_MAX * (double)EHS_SINT_8_MAX); default: return 0; } } SInt_16 Audio::SampleAsSInt_16(const UInt_64 sampleIndex) const { switch (dataType) { case DataType::SINT_8: return (SInt_16)((double)((SInt_8*)data)[sampleIndex] / (double)EHS_SINT_8_MAX * (double)EHS_SINT_16_MAX); case DataType::SINT_16: return ((SInt_16 *)data)[sampleIndex]; case DataType::FLOAT: return (SInt_16)(((double *)data)[sampleIndex] * (double)EHS_SINT_16_MAX); case DataType::SINT_32: return (SInt_16)((double)((SInt_32 *)data)[sampleIndex] / (double)EHS_SINT_32_MAX * (double)EHS_SINT_16_MAX); case DataType::SINT_64: return (SInt_16)((double)((SInt_64 *)data)[sampleIndex] / (double)EHS_SINT_64_MAX * (double)EHS_SINT_16_MAX); default: return 0; } } float Audio::SampleAsFloat(const UInt_64 sampleIndex) const { switch (dataType) { case DataType::SINT_8: return (float)((SInt_8*)data)[sampleIndex] / (float)EHS_SINT_8_MAX; case DataType::SINT_16: return (float)((SInt_16*)data)[sampleIndex] / (float)EHS_SINT_16_MAX; case DataType::FLOAT: return ((float*)data)[sampleIndex]; case DataType::SINT_32: return (float)((SInt_32*)data)[sampleIndex] / (float)EHS_SINT_32_MAX; case DataType::SINT_64: return (float)((SInt_64*)data)[sampleIndex] / (float)EHS_SINT_64_MAX; default: return 0; } } SInt_32 Audio::SampleAsSInt_32(const UInt_64 sampleIndex) const { switch (dataType) { case DataType::SINT_8: return (SInt_32)((double)((SInt_8 *)data)[sampleIndex] / (double)EHS_SINT_8_MAX * (double)EHS_SINT_32_MAX); case DataType::SINT_16: return (SInt_32)((double)((SInt_16 *)data)[sampleIndex] / (double)EHS_SINT_16_MAX * (double)EHS_SINT_32_MAX); case DataType::FLOAT: return (SInt_32)(((double *)data)[sampleIndex] * (double)EHS_SINT_32_MAX); case DataType::SINT_32: return ((SInt_32 *)data)[sampleIndex]; case DataType::SINT_64: return (SInt_32)((double)((SInt_64 *)data)[sampleIndex] / (double)EHS_SINT_64_MAX * (double)EHS_SINT_32_MAX); default: return 0; } } SInt_64 Audio::SampleAsSInt_64(const UInt_64 sampleIndex) const { switch (dataType) { case DataType::SINT_8: return (SInt_64)((double)((SInt_8 *)data)[sampleIndex] / (double)EHS_SINT_8_MAX * (double)EHS_SINT_64_MAX); case DataType::SINT_16: return (SInt_64)((double)((SInt_16 *)data)[sampleIndex] / (double)EHS_SINT_16_MAX * (double)EHS_SINT_64_MAX); case DataType::FLOAT: return (SInt_64)(((double *)data)[sampleIndex] * (double)EHS_SINT_64_MAX); case DataType::SINT_32: return (SInt_64)((double)((SInt_32 *)data)[sampleIndex] / (double)EHS_SINT_32_MAX * (double)EHS_SINT_64_MAX); case DataType::SINT_64: return ((SInt_64 *)data)[sampleIndex]; default: return 0; } } SInt_8 Audio::PeakAsSInt_8() const { switch (dataType) { case DataType::SINT_8: return *(SInt_8*)peak; case DataType::SINT_16: return (SInt_8)((double)*(SInt_16 *)peak / (double)EHS_SINT_16_MAX * (double)EHS_SINT_8_MAX); case DataType::FLOAT: return (SInt_8)(*(double *)peak * (double)EHS_SINT_8_MAX); case DataType::SINT_32: return (SInt_8)((double)*(SInt_32 *)peak / (double)EHS_SINT_32_MAX * (double)EHS_SINT_8_MAX); case DataType::SINT_64: return (SInt_8)((double)*(SInt_64 *)peak / (double)EHS_SINT_64_MAX * (double)EHS_SINT_8_MAX); default: return 0; } } SInt_16 Audio::PeakAsSInt_16() const { switch (dataType) { case DataType::SINT_8: return (SInt_16)((double)*(SInt_8 *)peak / (double)EHS_SINT_8_MAX * (double)EHS_SINT_16_MAX); case DataType::SINT_16: return *(SInt_16*)peak; case DataType::FLOAT: return (SInt_16)(*(double*)peak * (double)EHS_SINT_16_MAX); case DataType::SINT_32: return (SInt_16)((double)*(SInt_32 *)peak / (double)EHS_SINT_32_MAX * (double)EHS_SINT_16_MAX); case DataType::SINT_64: return (SInt_16)((double)*(SInt_64 *)peak / (double)EHS_SINT_64_MAX * (double)EHS_SINT_16_MAX); default: return 0; } } float Audio::PeakAsFloat() const { switch (dataType) { case DataType::SINT_8: return (float)*(SInt_8*)peak / (float)EHS_SINT_8_MAX; case DataType::SINT_16: return (float)*(SInt_16*)peak / (float)EHS_SINT_16_MAX; case DataType::FLOAT: return *(float*)peak; case DataType::SINT_32: return (float)*(SInt_32*)peak / (float)EHS_SINT_32_MAX; case DataType::SINT_64: return (float)*(SInt_64*)peak / (float)EHS_SINT_64_MAX; default: return 0; } } SInt_32 Audio::PeakAsSInt_32() const { switch (dataType) { case DataType::SINT_8: return (SInt_32)((double)*(SInt_8 *)peak / (double)EHS_SINT_8_MAX * (double)EHS_SINT_32_MAX); case DataType::SINT_16: return (SInt_32)((double)*(SInt_16 *)peak / (double)EHS_SINT_16_MAX * (double)EHS_SINT_32_MAX); case DataType::FLOAT: return (SInt_32)(*(double *)peak * (double)EHS_SINT_32_MAX); case DataType::SINT_32: return *(SInt_32 *)peak; case DataType::SINT_64: return (SInt_32)((double)*(SInt_64 *)peak / (double)EHS_SINT_64_MAX * (double)EHS_SINT_32_MAX); default: return 0; } } SInt_64 Audio::PeakAsSInt_64() const { switch (dataType) { case DataType::SINT_8: return (SInt_64)((double)*(SInt_8 *)peak / (double)EHS_SINT_8_MAX * (double)EHS_SINT_64_MAX); case DataType::SINT_16: return (SInt_64)((double)*(SInt_16 *)peak / (double)EHS_SINT_16_MAX * (double)EHS_SINT_64_MAX); case DataType::FLOAT: return (SInt_64)(*(double *)peak * (double)EHS_SINT_64_MAX); case DataType::SINT_32: return (SInt_64)((double)*(SInt_32 *)peak / (double)EHS_SINT_32_MAX * (double)EHS_SINT_64_MAX); case DataType::SINT_64: return *(SInt_64 *)peak; default: return 0; } } void Audio::SetPeak(const UInt_64 size, const Byte* newPeak) { Util::Copy(peak, newPeak, size); } const Byte* Audio::GetPeak() const { return peak; } void Audio::ToDataType(const DataType newDataType) { if (dataType == newDataType) return; UInt_8 newByteDepth = ToByteDepth(newDataType); Byte* newData = new Byte[GetSampleCount() * newByteDepth]; Byte* newPeak = new Byte[newByteDepth]; if (dataType == DataType::SINT_16 && newDataType == DataType::SINT_8) SInt_16_to_SInt_8(newData, newPeak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_8) Float_to_SInt_8(newData, newPeak); else if (dataType == DataType::SINT_32 && newDataType == DataType::SINT_8) SInt_32_to_SInt_8(newData, newPeak); else if (dataType == DataType::SINT_64 && newDataType == DataType::SINT_8) SInt_64_to_SInt_8(newData, newPeak); else if (dataType == DataType::SINT_8 && newDataType == DataType::SINT_16) SInt_8_to_SInt_16(newData, newPeak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_16) Float_to_SInt_16(newData, newPeak); else if (dataType == DataType::SINT_32 && newDataType == DataType::SINT_16) SInt_32_to_SInt_16(newData, newPeak); else if (dataType == DataType::SINT_64 && newDataType == DataType::SINT_16) SInt_64_to_SInt_16(newData, newPeak); else if (dataType == DataType::SINT_8 && newDataType == DataType::FLOAT) SInt_8_to_Float(newData, newPeak); else if (dataType == DataType::SINT_16 && newDataType == DataType::FLOAT) SInt_16_to_Float(newData, newPeak); else if (dataType == DataType::SINT_32 && newDataType == DataType::FLOAT) SInt_32_to_Float(newData, newPeak); else if (dataType == DataType::SINT_64 && newDataType == DataType::FLOAT) SInt_64_to_Float(newData, newPeak); else if (dataType == DataType::SINT_8 && newDataType == DataType::SINT_32) SInt_8_to_SInt_32(newData, newPeak); else if (dataType == DataType::SINT_16 && newDataType == DataType::SINT_32) SInt_16_to_SInt_32(newData, newPeak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_32) Float_to_SInt_32(newData, newPeak); else if (dataType == DataType::SINT_64 && newDataType == DataType::SINT_32) SInt_64_to_SInt_32(newData, newPeak); else if (dataType == DataType::SINT_8 && newDataType == DataType::SINT_64) SInt_8_to_SInt_64(newData, newPeak); else if (dataType == DataType::SINT_16 && newDataType == DataType::SINT_64) SInt_16_to_SInt_64(newData, newPeak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_64) Float_to_SInt_64(newData, newPeak); else if (dataType == DataType::SINT_32 && newDataType == DataType::SINT_64) SInt_32_to_SInt_64(newData, newPeak); dataType = newDataType; byteDepth = ToByteDepth(newDataType); delete[] data; data = newData; delete[] peak; peak = newPeak; } Audio Audio::GetAsDataType(const DataType newDataType) const { if (dataType == newDataType) return *this; Audio result; result.sampleRate = sampleRate; result.dataType = newDataType; result.byteDepth = ToByteDepth(newDataType); result.channels = channels; result.frames = frames; result.length = length; result.data = new Byte[result.GetSize()]; result.peak = new Byte[result.byteDepth]; if (dataType == DataType::SINT_16 && newDataType == DataType::SINT_8) SInt_16_to_SInt_8(result.data, result.peak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_8) Float_to_SInt_8(result.data, result.peak); else if (dataType == DataType::SINT_32 && newDataType == DataType::SINT_8) SInt_32_to_SInt_8(result.data, result.peak); else if (dataType == DataType::SINT_64 && newDataType == DataType::SINT_8) SInt_64_to_SInt_8(result.data, result.peak); else if (dataType == DataType::SINT_8 && newDataType == DataType::SINT_16) SInt_8_to_SInt_16(result.data, result.peak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_16) Float_to_SInt_16(result.data, result.peak); else if (dataType == DataType::SINT_32 && newDataType == DataType::SINT_16) SInt_32_to_SInt_16(result.data, result.peak); else if (dataType == DataType::SINT_64 && newDataType == DataType::SINT_16) SInt_64_to_SInt_16(result.data, result.peak); else if (dataType == DataType::SINT_8 && newDataType == DataType::FLOAT) SInt_8_to_Float(result.data, result.peak); else if (dataType == DataType::SINT_16 && newDataType == DataType::FLOAT) SInt_16_to_Float(result.data, result.peak); else if (dataType == DataType::SINT_32 && newDataType == DataType::FLOAT) SInt_32_to_Float(result.data, result.peak); else if (dataType == DataType::SINT_64 && newDataType == DataType::FLOAT) SInt_64_to_Float(result.data, result.peak); else if (dataType == DataType::SINT_8 && newDataType == DataType::SINT_32) SInt_8_to_SInt_32(result.data, result.peak); else if (dataType == DataType::SINT_16 && newDataType == DataType::SINT_32) SInt_16_to_SInt_32(result.data, result.peak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_32) Float_to_SInt_32(result.data, result.peak); else if (dataType == DataType::SINT_64 && newDataType == DataType::SINT_32) SInt_64_to_SInt_32(result.data, result.peak); else if (dataType == DataType::SINT_8 && newDataType == DataType::SINT_64) SInt_8_to_SInt_64(result.data, result.peak); else if (dataType == DataType::SINT_16 && newDataType == DataType::SINT_64) SInt_16_to_SInt_64(result.data, result.peak); else if (dataType == DataType::FLOAT && newDataType == DataType::SINT_64) Float_to_SInt_64(result.data, result.peak); else if (dataType == DataType::SINT_32 && newDataType == DataType::SINT_64) SInt_32_to_SInt_64(result.data, result.peak); return result; } void Audio::ToChannels(const UInt_8 newChannels) { if (!data || newChannels == channels) return; Byte* result; if (newChannels == 1) { result = new Byte[byteDepth * newChannels * frames]; ToMono(frames, result, 0); } else if (channels == 1 && newChannels == 2) { result = new Byte[byteDepth * newChannels * frames]; Mono_to_Stereo(frames, result, 0); } else if (channels == 6 && newChannels == 2) { result = new Byte[byteDepth * newChannels * frames]; Five_One_to_Stereo(frames, result, 0); } else if (channels == 8 && newChannels == 2) { result = new Byte[byteDepth * newChannels * frames]; Seven_One_to_Stereo(frames, result, 0); } else if (channels == 1 && newChannels == 6) { result = new Byte[byteDepth * newChannels * frames]; Mono_to_Five_One(frames, result, 0); } else if (channels == 2 && newChannels == 6) { result = new Byte[byteDepth * newChannels * frames]; Stereo_to_Five_One(frames, result, 0); } else if (channels == 8 && newChannels == 6) { result = new Byte[byteDepth * newChannels * frames]; Seven_One_to_Five_One(frames, result, 0); } else if (channels == 1 && newChannels == 8) { result = new Byte[byteDepth * newChannels * frames]; Mono_to_Seven_One(frames, result, 0); } else if (channels == 2 && newChannels == 8) { result = new Byte[byteDepth * newChannels * frames]; Stereo_to_Seven_One(frames, result, 0); } else if (channels == 6 && newChannels == 8) { result = new Byte[byteDepth * newChannels * frames]; Five_One_to_Seven_One(frames, result, 0); } else { EHS_LOG_INT(LogType::ERR, 0, "Conversion from " + Str_8::FromNum(channels) + " channels, to " + Str_8::FromNum(newChannels) + " channels is unsupported."); return; } channels = newChannels; delete[] data; data = result; } Audio Audio::GetAsChannels(const UInt_8 newChannels) const { Audio result; if (!data || newChannels == channels) return result; if (newChannels == 1) { result.data = new Byte[byteDepth * newChannels * frames]; ToMono(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 1 && newChannels == 2) { result.data = new Byte[byteDepth * newChannels * frames]; Mono_to_Stereo(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 6 && newChannels == 2) { result.data = new Byte[byteDepth * newChannels * frames]; Five_One_to_Stereo(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 8 && newChannels == 2) { result.data = new Byte[byteDepth * newChannels * frames]; Seven_One_to_Stereo(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 1 && newChannels == 6) { result.data = new Byte[byteDepth * newChannels * frames]; Mono_to_Five_One(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 2 && newChannels == 6) { result.data = new Byte[byteDepth * newChannels * frames]; Stereo_to_Five_One(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 8 && newChannels == 6) { result.data = new Byte[byteDepth * newChannels * frames]; Seven_One_to_Five_One(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 1 && newChannels == 8) { result.data = new Byte[byteDepth * newChannels * frames]; Mono_to_Seven_One(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 2 && newChannels == 8) { result.data = new Byte[byteDepth * newChannels * frames]; Stereo_to_Seven_One(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else if (channels == 6 && newChannels == 8) { result.data = new Byte[byteDepth * newChannels * frames]; Five_One_to_Seven_One(frames, result.data, 0); result.peak = new Byte[byteDepth]; Util::Copy(result.peak, peak, byteDepth); } else { EHS_LOG_INT(LogType::ERR, 0, "Conversion from " + Str_8::FromNum(channels) + " channels, to " + Str_8::FromNum(newChannels) + " channels is unsupported."); return result; } result.sampleRate = sampleRate; result.dataType = dataType; result.byteDepth = byteDepth; result.channels = newChannels; result.frames = frames; result.length = (float)frames / (float)sampleRate; return result; } bool Audio::Export(const Str_8& filePath) const { Str_8 ext = File::ParseExt_8(filePath); const AudioCodec* codec = GetCodec(ext); if (!codec) { EHS_LOG_INT(LogType::ERR, 0, "Codec not found for file extension, \"" + ext + "\"."); return false; } Serializer result; if (!codec->Encode(result, this)) return false; File file(filePath, Mode::WRITE, Disposition::CREATE_PERSISTENT); file.WriteSerializer_64(result); return true; } void Audio::ToMono(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffset = channels * (frameOffset + i); ((SInt_8*)newData)[i] = (((SInt_8*)data)[sampleOffset] + ((SInt_8*)data)[sampleOffset + 1]) / (PeakAsSInt_8() * 2); } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffset = channels * (frameOffset + i); ((SInt_16*)newData)[i] = (((SInt_16*)data)[sampleOffset] + ((SInt_16*)data)[sampleOffset + 1]) / (PeakAsSInt_16() * 2); } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffset = channels * (frameOffset + i); ((float*)newData)[i] = (((float*)data)[sampleOffset] + ((float*)data)[sampleOffset + 1]) / (PeakAsFloat() * 2.0f); } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffset = channels * (frameOffset + i); ((SInt_32*)newData)[i] = (((SInt_32*)data)[sampleOffset] + ((SInt_32*)data)[sampleOffset + 1]) / (PeakAsSInt_32() * 2); } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffset = channels * (frameOffset + i); ((SInt_64*)newData)[i] = (((SInt_64*)data)[sampleOffset] + ((SInt_64*)data)[sampleOffset + 1]) / (PeakAsSInt_64() * 2); } return; } default: return; } } void Audio::Mono_to_Stereo(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = frameOffset + i; ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB]; } return; } default: return; } } void Audio::Five_One_to_Stereo(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB + 1]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB + 1]; } return; } default: return; } } void Audio::Seven_One_to_Stereo(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB + 1]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 2 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB + 1]; } return; } default: return; } } void Audio::Mono_to_Five_One(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 2] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 3] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 4] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 5] = ((SInt_8*)data)[sampleOffsetB]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 2] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 3] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 4] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 5] = ((SInt_16*)data)[sampleOffsetB]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = frameOffset + i; ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 2] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 3] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 4] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 5] = ((float*)data)[sampleOffsetB]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 2] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 3] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 4] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 5] = ((SInt_32*)data)[sampleOffsetB]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 2] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 3] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 4] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 5] = ((SInt_64*)data)[sampleOffsetB]; } return; } default: return; } } void Audio::Stereo_to_Five_One(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB + 1]; ((SInt_8*)newData)[sampleOffsetA + 2] = (((SInt_8*)data)[sampleOffsetB] + ((SInt_8*)data)[sampleOffsetB + 1]) / (PeakAsSInt_8() * 2); ((SInt_8*)newData)[sampleOffsetA + 3] = ((SInt_8*)newData)[sampleOffsetA + 2]; ((SInt_8*)newData)[sampleOffsetA + 4] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 5] = ((SInt_8*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB + 1]; ((SInt_16*)newData)[sampleOffsetA + 2] = (((SInt_16*)data)[sampleOffsetB] + ((SInt_16*)data)[sampleOffsetB + 1]) / (PeakAsSInt_16() * 2); ((SInt_16*)newData)[sampleOffsetA + 3] = ((SInt_16*)newData)[sampleOffsetA + 2]; ((SInt_16*)newData)[sampleOffsetA + 4] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 5] = ((SInt_16*)data)[sampleOffsetB + 1]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB + 1]; ((float*)newData)[sampleOffsetA + 2] = (((float*)data)[sampleOffsetB] + ((float*)data)[sampleOffsetB + 1]) / (PeakAsFloat() * 2.0f); ((float*)newData)[sampleOffsetA + 3] = ((float*)newData)[sampleOffsetA + 2]; ((float*)newData)[sampleOffsetA + 4] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 5] = ((float*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB + 1]; ((SInt_32*)newData)[sampleOffsetA + 2] = (((SInt_32*)data)[sampleOffsetB] + ((SInt_32*)data)[sampleOffsetB + 1]) / (PeakAsSInt_32() * 2); ((SInt_32*)newData)[sampleOffsetA + 3] = ((SInt_32*)newData)[sampleOffsetA + 2]; ((SInt_32*)newData)[sampleOffsetA + 4] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 5] = ((SInt_32*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB + 1]; ((SInt_64*)newData)[sampleOffsetA + 2] = (((SInt_64*)data)[sampleOffsetB] + ((SInt_64*)data)[sampleOffsetB + 1]) / (PeakAsSInt_64() * 2); ((SInt_64*)newData)[sampleOffsetA + 3] = ((SInt_64*)newData)[sampleOffsetA + 2]; ((SInt_64*)newData)[sampleOffsetA + 4] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 5] = ((SInt_64*)data)[sampleOffsetB + 1]; } return; } default: return; } } void Audio::Seven_One_to_Five_One(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB + 1]; ((SInt_8*)newData)[sampleOffsetA + 2] = ((SInt_8*)data)[sampleOffsetB + 2]; ((SInt_8*)newData)[sampleOffsetA + 3] = ((SInt_8*)data)[sampleOffsetB + 3]; ((SInt_8*)newData)[sampleOffsetA + 4] = ((SInt_8*)data)[sampleOffsetB + 4]; ((SInt_8*)newData)[sampleOffsetA + 5] = ((SInt_8*)data)[sampleOffsetB + 5]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB + 1]; ((SInt_16*)newData)[sampleOffsetA + 2] = ((SInt_16*)data)[sampleOffsetB + 2]; ((SInt_16*)newData)[sampleOffsetA + 3] = ((SInt_16*)data)[sampleOffsetB + 3]; ((SInt_16*)newData)[sampleOffsetA + 4] = ((SInt_16*)data)[sampleOffsetB + 4]; ((SInt_16*)newData)[sampleOffsetA + 5] = ((SInt_16*)data)[sampleOffsetB + 5]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB + 1]; ((float*)newData)[sampleOffsetA + 2] = ((float*)data)[sampleOffsetB + 2]; ((float*)newData)[sampleOffsetA + 3] = ((float*)data)[sampleOffsetB + 3]; ((float*)newData)[sampleOffsetA + 4] = ((float*)data)[sampleOffsetB + 4]; ((float*)newData)[sampleOffsetA + 5] = ((float*)data)[sampleOffsetB + 5]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB + 1]; ((SInt_32*)newData)[sampleOffsetA + 2] = ((SInt_32*)data)[sampleOffsetB + 2]; ((SInt_32*)newData)[sampleOffsetA + 3] = ((SInt_32*)data)[sampleOffsetB + 3]; ((SInt_32*)newData)[sampleOffsetA + 4] = ((SInt_32*)data)[sampleOffsetB + 4]; ((SInt_32*)newData)[sampleOffsetA + 5] = ((SInt_32*)data)[sampleOffsetB + 5]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 6 * i; UInt_64 sampleOffsetB = 8 * (frameOffset + i); ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB + 1]; ((SInt_64*)newData)[sampleOffsetA + 2] = ((SInt_64*)data)[sampleOffsetB + 2]; ((SInt_64*)newData)[sampleOffsetA + 3] = ((SInt_64*)data)[sampleOffsetB + 3]; ((SInt_64*)newData)[sampleOffsetA + 4] = ((SInt_64*)data)[sampleOffsetB + 4]; ((SInt_64*)newData)[sampleOffsetA + 5] = ((SInt_64*)data)[sampleOffsetB + 5]; } return; } default: return; } } void Audio::Mono_to_Seven_One(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 2] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 3] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 4] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 5] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 6] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 7] = ((SInt_8*)data)[sampleOffsetB]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 2] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 3] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 4] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 5] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 6] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 7] = ((SInt_16*)data)[sampleOffsetB]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = frameOffset + i; ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 2] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 3] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 4] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 5] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 6] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 7] = ((float*)data)[sampleOffsetB]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 2] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 3] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 4] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 5] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 6] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 7] = ((SInt_32*)data)[sampleOffsetB]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = frameOffset + i; ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 2] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 3] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 4] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 5] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 6] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 7] = ((SInt_64*)data)[sampleOffsetB]; } return; } default: return; } } void Audio::Stereo_to_Seven_One(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB + 1]; ((SInt_8*)newData)[sampleOffsetA + 2] = (((SInt_8*)data)[sampleOffsetB] + ((SInt_8*)data)[sampleOffsetB + 1]) / (PeakAsSInt_8() * 2); ((SInt_8*)newData)[sampleOffsetA + 3] = ((SInt_8*)newData)[sampleOffsetA + 2]; ((SInt_8*)newData)[sampleOffsetA + 4] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 5] = ((SInt_8*)data)[sampleOffsetB + 1]; ((SInt_8*)newData)[sampleOffsetA + 6] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 7] = ((SInt_8*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB + 1]; ((SInt_16*)newData)[sampleOffsetA + 2] = (((SInt_16*)data)[sampleOffsetB] + ((SInt_16*)data)[sampleOffsetB + 1]) / (PeakAsSInt_16() * 2); ((SInt_16*)newData)[sampleOffsetA + 3] = ((SInt_16*)newData)[sampleOffsetA + 2]; ((SInt_16*)newData)[sampleOffsetA + 4] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 5] = ((SInt_16*)data)[sampleOffsetB + 1]; ((SInt_16*)newData)[sampleOffsetA + 6] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 7] = ((SInt_16*)data)[sampleOffsetB + 1]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB + 1]; ((float*)newData)[sampleOffsetA + 2] = (((float*)data)[sampleOffsetB] + ((float*)data)[sampleOffsetB + 1]) / (PeakAsFloat() * 2.0f); ((float*)newData)[sampleOffsetA + 3] = ((float*)newData)[sampleOffsetA + 2]; ((float*)newData)[sampleOffsetA + 4] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 5] = ((float*)data)[sampleOffsetB + 1]; ((float*)newData)[sampleOffsetA + 6] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 7] = ((float*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB + 1]; ((SInt_32*)newData)[sampleOffsetA + 2] = (((SInt_32*)data)[sampleOffsetB] + ((SInt_32*)data)[sampleOffsetB + 1]) / (PeakAsSInt_32() * 2); ((SInt_32*)newData)[sampleOffsetA + 3] = ((SInt_32*)newData)[sampleOffsetA + 2]; ((SInt_32*)newData)[sampleOffsetA + 4] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 5] = ((SInt_32*)data)[sampleOffsetB + 1]; ((SInt_32*)newData)[sampleOffsetA + 6] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 7] = ((SInt_32*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 2 * (frameOffset + i); ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB + 1]; ((SInt_64*)newData)[sampleOffsetA + 2] = (((SInt_64*)data)[sampleOffsetB] + ((SInt_64*)data)[sampleOffsetB + 1]) / (PeakAsSInt_64() * 2); ((SInt_64*)newData)[sampleOffsetA + 3] = ((SInt_64*)newData)[sampleOffsetA + 2]; ((SInt_64*)newData)[sampleOffsetA + 4] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 5] = ((SInt_64*)data)[sampleOffsetB + 1]; ((SInt_64*)newData)[sampleOffsetA + 6] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 7] = ((SInt_64*)data)[sampleOffsetB + 1]; } return; } default: return; } } void Audio::Five_One_to_Seven_One(const UInt_64 newFrameCount, Byte* newData, const UInt_64 frameOffset) const { switch (dataType) { case DataType::SINT_8: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_8*)newData)[sampleOffsetA] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 1] = ((SInt_8*)data)[sampleOffsetB + 1]; ((SInt_8*)newData)[sampleOffsetA + 2] = ((SInt_8*)data)[sampleOffsetB + 2]; ((SInt_8*)newData)[sampleOffsetA + 3] = ((SInt_8*)data)[sampleOffsetB + 3]; ((SInt_8*)newData)[sampleOffsetA + 4] = ((SInt_8*)data)[sampleOffsetB + 4]; ((SInt_8*)newData)[sampleOffsetA + 5] = ((SInt_8*)data)[sampleOffsetB + 5]; ((SInt_8*)newData)[sampleOffsetA + 6] = ((SInt_8*)data)[sampleOffsetB]; ((SInt_8*)newData)[sampleOffsetA + 7] = ((SInt_8*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_16: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_16*)newData)[sampleOffsetA] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 1] = ((SInt_16*)data)[sampleOffsetB + 1]; ((SInt_16*)newData)[sampleOffsetA + 2] = ((SInt_16*)data)[sampleOffsetB + 2]; ((SInt_16*)newData)[sampleOffsetA + 3] = ((SInt_16*)data)[sampleOffsetB + 3]; ((SInt_16*)newData)[sampleOffsetA + 4] = ((SInt_16*)data)[sampleOffsetB + 4]; ((SInt_16*)newData)[sampleOffsetA + 5] = ((SInt_16*)data)[sampleOffsetB + 5]; ((SInt_16*)newData)[sampleOffsetA + 6] = ((SInt_16*)data)[sampleOffsetB]; ((SInt_16*)newData)[sampleOffsetA + 7] = ((SInt_16*)data)[sampleOffsetB + 1]; } return; } case DataType::FLOAT: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((float*)newData)[sampleOffsetA] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 1] = ((float*)data)[sampleOffsetB + 1]; ((float*)newData)[sampleOffsetA + 2] = ((float*)data)[sampleOffsetB + 2]; ((float*)newData)[sampleOffsetA + 3] = ((float*)data)[sampleOffsetB + 3]; ((float*)newData)[sampleOffsetA + 4] = ((float*)data)[sampleOffsetB + 4]; ((float*)newData)[sampleOffsetA + 5] = ((float*)data)[sampleOffsetB + 5]; ((float*)newData)[sampleOffsetA + 6] = ((float*)data)[sampleOffsetB]; ((float*)newData)[sampleOffsetA + 7] = ((float*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_32: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_32*)newData)[sampleOffsetA] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 1] = ((SInt_32*)data)[sampleOffsetB + 1]; ((SInt_32*)newData)[sampleOffsetA + 2] = ((SInt_32*)data)[sampleOffsetB + 2]; ((SInt_32*)newData)[sampleOffsetA + 3] = ((SInt_32*)data)[sampleOffsetB + 3]; ((SInt_32*)newData)[sampleOffsetA + 4] = ((SInt_32*)data)[sampleOffsetB + 4]; ((SInt_32*)newData)[sampleOffsetA + 5] = ((SInt_32*)data)[sampleOffsetB + 5]; ((SInt_32*)newData)[sampleOffsetA + 6] = ((SInt_32*)data)[sampleOffsetB]; ((SInt_32*)newData)[sampleOffsetA + 7] = ((SInt_32*)data)[sampleOffsetB + 1]; } return; } case DataType::SINT_64: { for (UInt_64 i = 0; i < newFrameCount; ++i) { UInt_64 sampleOffsetA = 8 * i; UInt_64 sampleOffsetB = 6 * (frameOffset + i); ((SInt_64*)newData)[sampleOffsetA] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 1] = ((SInt_64*)data)[sampleOffsetB + 1]; ((SInt_64*)newData)[sampleOffsetA + 2] = ((SInt_64*)data)[sampleOffsetB + 2]; ((SInt_64*)newData)[sampleOffsetA + 3] = ((SInt_64*)data)[sampleOffsetB + 3]; ((SInt_64*)newData)[sampleOffsetA + 4] = ((SInt_64*)data)[sampleOffsetB + 4]; ((SInt_64*)newData)[sampleOffsetA + 5] = ((SInt_64*)data)[sampleOffsetB + 5]; ((SInt_64*)newData)[sampleOffsetA + 6] = ((SInt_64*)data)[sampleOffsetB]; ((SInt_64*)newData)[sampleOffsetA + 7] = ((SInt_64*)data)[sampleOffsetB + 1]; } return; } default: return; } } void Audio::SInt_16_to_SInt_8(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) newData[a] = (Byte)((double)((SInt_16*)data)[a] / (double)EHS_SINT_16_MAX * (double)EHS_SINT_8_MAX); *(SInt_8*)newPeak = (SInt_8)((double)*(SInt_16*)peak / (double)EHS_SINT_16_MAX * (double)EHS_SINT_8_MAX); } void Audio::Float_to_SInt_8(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_8*)newData)[a] = (SInt_8)((double)((float*)data)[a] * (double)EHS_SINT_8_MAX); *(SInt_8*)newPeak = (SInt_8)((double)(*(float*)peak) * (double)EHS_SINT_8_MAX); } void Audio::SInt_32_to_SInt_8(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) newData[a] = (Byte)((double)((SInt_32*)data)[a] / (double)EHS_SINT_32_MAX * (double)EHS_SINT_8_MAX); *(SInt_8*)newPeak = (SInt_8)((double)*(SInt_32*)peak / (double)EHS_SINT_32_MAX * (double)EHS_SINT_8_MAX); } void Audio::SInt_64_to_SInt_8(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) newData[a] = (Byte)((double)((SInt_64*)data)[a] / (double)EHS_SINT_64_MAX * (double)EHS_SINT_8_MAX); *(SInt_8*)newPeak = (SInt_8)((double)*(SInt_64*)peak / (double)EHS_SINT_64_MAX * (double)EHS_SINT_8_MAX); } void Audio::SInt_8_to_SInt_16(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_16*)newData)[a] = (SInt_16)((double)(SInt_8)data[a] / (double)EHS_SINT_8_MAX * (double)EHS_SINT_16_MAX); *(SInt_16*)newPeak = (SInt_16)((double)*(SInt_8*)peak / (double)EHS_SINT_8_MAX * (double)EHS_SINT_16_MAX); } void Audio::Float_to_SInt_16(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_16*)newData)[a] = (SInt_16)((double)((float*)data)[a] * (double)EHS_SINT_16_MAX); *(SInt_16*)newPeak = (SInt_16)((double)(*(float*)peak) * (double)EHS_SINT_16_MAX); } void Audio::SInt_32_to_SInt_16(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_16*)newData)[a] = (SInt_16)((double)((SInt_32*)data)[a] / (double)EHS_SINT_32_MAX * (double)EHS_SINT_16_MAX); *(SInt_16*)newPeak = (SInt_16)((double)*(SInt_32*)peak / (double)EHS_SINT_32_MAX * (double)EHS_SINT_16_MAX); } void Audio::SInt_64_to_SInt_16(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_16*)newData)[a] = (SInt_16)((double)((SInt_64*)data)[a] / (double)EHS_SINT_64_MAX * (double)EHS_SINT_16_MAX); *(SInt_16*)newPeak = (SInt_16)((double)*(SInt_64*)peak / (double)EHS_SINT_64_MAX * (double)EHS_SINT_16_MAX); } void Audio::SInt_8_to_Float(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((float*)newData)[a] = (float)((double)(((SInt_8*)data)[a]) / (double)EHS_SINT_8_MAX); *(float*)newPeak = (float)((double)*(SInt_8*)peak / (double)EHS_SINT_8_MAX); } void Audio::SInt_16_to_Float(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((float*)newData)[a] = (float)((double)(((SInt_16*)data)[a]) / (double)EHS_SINT_16_MAX); *(float*)newPeak = (float)((double)*(SInt_16*)peak / (double)EHS_SINT_16_MAX); } void Audio::SInt_32_to_Float(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((float*)newData)[a] = (float)((double)(((SInt_32*)data)[a]) / (double)EHS_SINT_32_MAX); *(float*)newPeak = (float)((double)*(SInt_32*)peak / (double)EHS_SINT_32_MAX); } void Audio::SInt_64_to_Float(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((float*)newData)[a] = (float)((double)(((SInt_64*)data)[a]) / (double)EHS_SINT_64_MAX); *(float*)newPeak = (float)((double)*(SInt_64*)peak / (double)EHS_SINT_64_MAX); } void Audio::SInt_8_to_SInt_32(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_32*)newData)[a] = (SInt_32)((double)(SInt_8)data[a] / (double)EHS_SINT_8_MAX * (double)EHS_SINT_32_MAX); *(SInt_32*)newPeak = (SInt_32)((double)*(SInt_8*)peak / (double)EHS_SINT_8_MAX * (double)EHS_SINT_32_MAX); } void Audio::SInt_16_to_SInt_32(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_32*)newData)[a] = (SInt_32)((double)((SInt_16*)data)[a] / (double)EHS_SINT_16_MAX * (double)EHS_SINT_32_MAX); *(SInt_32*)newPeak = (SInt_32)((double)*(SInt_16*)peak / (double)EHS_SINT_16_MAX * (double)EHS_SINT_32_MAX); } void Audio::Float_to_SInt_32(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_32*)newData)[a] = (SInt_32)(((double*)data)[a] * (double)EHS_SINT_32_MAX); *(SInt_32*)newPeak = (SInt_32)(*(double*)peak * (double)EHS_SINT_32_MAX); } void Audio::SInt_64_to_SInt_32(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_32*)newData)[a] = (SInt_32)((double)((SInt_64*)data)[a] / (double)EHS_SINT_64_MAX * (double)EHS_SINT_32_MAX); *(SInt_32*)newPeak = (SInt_32)((double)*(SInt_64*)peak / (double)EHS_SINT_64_MAX * (double)EHS_SINT_32_MAX); } void Audio::SInt_8_to_SInt_64(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_64*)newData)[a] = (SInt_64)((double)(SInt_8)data[a] / (double)EHS_SINT_8_MAX * (double)EHS_SINT_64_MAX); *(SInt_64*)newPeak = (SInt_64)((double)*(SInt_8*)peak / (double)EHS_SINT_8_MAX * (double)EHS_SINT_64_MAX); } void Audio::SInt_16_to_SInt_64(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_64*)newData)[a] = (SInt_64)((double)((SInt_16*)data)[a] / (double)EHS_SINT_16_MAX * (double)EHS_SINT_64_MAX); *(SInt_64*)newPeak = (SInt_64)((double)*(SInt_16*)peak / (double)EHS_SINT_16_MAX * (double)EHS_SINT_64_MAX); } void Audio::Float_to_SInt_64(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_64*)newData)[a] = (SInt_64)(((double*)data)[a] * (double)EHS_SINT_64_MAX); *(SInt_64*)newPeak = (SInt_64)(*(double*)peak * (double)EHS_SINT_64_MAX); } void Audio::SInt_32_to_SInt_64(Byte* newData, Byte* newPeak) const { for (UInt_64 a = 0; a < GetSampleCount(); ++a) ((SInt_64*)newData)[a] = (SInt_64)((double)((SInt_32*)data)[a] / (double)EHS_SINT_32_MAX * (double)EHS_SINT_64_MAX); *(SInt_64*)newPeak = (SInt_64)((double)*(SInt_32*)peak / (double)EHS_SINT_32_MAX * (double)EHS_SINT_64_MAX); } bool EncodeEHA(const ehs::AudioCodec* const codec, ehs::Serializer& out, const ehs::Audio* const in) { Serializer result(codec->GetEndianness()); result.WriteVersion({1, 0, 0}); result.Write(in->GetSampleRate()); result.Write(in->GetDataType()); result.Write(in->GetByteDepth()); result.Write(in->GetChannels()); result.Write(in->GetFrameCount()); UInt_64 size = in->GetSize(); UInt_8 byteDepth = in->GetByteDepth(); result.Resize(result.Size() + size + byteDepth); Util::Copy(&result[result.GetOffset()], &in[0], size); result.SetOffset(result.GetOffset() + size); Util::Copy(&result[result.GetOffset()], in->GetPeak(), byteDepth); return true; } bool DecodeEHA(const ehs::AudioCodec* const codec, ehs::Serializer& in, ehs::Audio* const out) { Version version = in.ReadVersion(); if (version != Version(1, 0, 0)) { EHS_LOG_INT(LogType::ERR, 0, "Incompatible audio file version."); return false; } UInt_64 sampleRate = in.Read(); DataType dataType = in.Read(); UInt_8 byteDepth = in.Read(); UInt_8 channels = in.Read(); UInt_64 frames = in.Read(); *out = Audio(out->GetId(), sampleRate, dataType, channels, frames); UInt_64 size = out->GetSize(); Util::Copy(&(*out)[0], &in[in.GetOffset()], size); in.SetOffset(in.GetOffset() + size); out->SetPeak(byteDepth, &in[in.GetOffset()]); return true; } bool DecodeWAV(const ehs::AudioCodec* const codec, ehs::Serializer& in, ehs::Audio* out) { RIFF riff(in); if (riff.GetType() != "WAVE") { EHS_LOG_INT(LogType::ERR, 0, "Data is not in WAVE format."); return false; } RIFF_Chunk fmt = riff.GetChunk("fmt "); if (!fmt.IsValid()) { EHS_LOG_INT(LogType::ERR, 1, "Wave does not have a format chunk."); return false; } Serializer<> fmtSer = fmt.GetData(); RIFF_Chunk dChunk = riff.GetChunk("data"); if (!dChunk.IsValid()) { EHS_LOG_INT(LogType::ERR, 2, "Wave does not have a data chunk."); return false; } UInt_16 compression = fmtSer.Read(); if (compression == 0x2) { EHS_LOG_INT(LogType::ERR, 3, "Microsoft ADPCM compression unsupported."); return false; } else if (compression == 0x6) { EHS_LOG_INT(LogType::ERR, 4, "ITU G.711 a-law compression unsupported."); return false; } else if (compression == 0x7) { EHS_LOG_INT(LogType::ERR, 5, "ITU G.711 µ-law compression unsupported."); return false; } else if (compression == 0x11) { EHS_LOG_INT(LogType::ERR, 6, "IMA ADPCM compression unsupported."); return false; } else if (compression == 0x16) { EHS_LOG_INT(LogType::ERR, 7, "TU G.723 ADPCM (Yamaha) compression unsupported."); return false; } else if (compression == 0x31) { EHS_LOG_INT(LogType::ERR, 8, "GSM 6.10 compression unsupported."); return false; } else if (compression == 0x40) { EHS_LOG_INT(LogType::ERR, 9, "ITU G.721 ADPCM compression unsupported."); return false; } else if (compression == 0x50) { EHS_LOG_INT(LogType::ERR, 10, "MPEG compression unsupported."); return false; } else if (compression == 0xFFFF) { EHS_LOG_INT(LogType::ERR, 11, "Experimental compression unsupported."); return false; } else if (compression != 0x1 && compression != 0x3) { EHS_LOG_INT(LogType::ERR, 12, "Wave has unknown compression of " + Str_8::FromNum(compression) + "."); return false; } UInt_16 channels = fmtSer.Read(); UInt_32 sampleRate = fmtSer.Read(); fmtSer.SetOffset(fmtSer.GetOffset() + 6); UInt_8 byteDepth = (UInt_8)(fmtSer.Read() / 8); DataType dataType; if (byteDepth == 1) dataType = DataType::SINT_8; else if (byteDepth == 2) dataType = DataType::SINT_16; else if (byteDepth == 3) dataType = DataType::SINT_24; else if (byteDepth == 4 && compression == 0x3) dataType = DataType::FLOAT; else if (byteDepth == 4) dataType = DataType::SINT_32; else if (byteDepth == 8) dataType = DataType::SINT_64; else return false; UInt_64 size = dChunk.GetData().Size(); UInt_64 frames = size / byteDepth / channels; *out = Audio(out->GetId(), sampleRate, dataType, channels, frames); Serializer<> dataSer = dChunk.GetData(); for (UInt_32 i = 0; i < dataSer.Size(); i += byteDepth) { if (byteDepth == 1) { *(SInt_8*)&(*out)[i] = dataSer.Read(); if ((*out)[i] > *(SInt_8*)out->GetPeak()) out->SetPeak(sizeof(SInt_8), &(*out)[i]); } else if (byteDepth == 2) { *(SInt_16*)&(*out)[i] = dataSer.Read(); if (*(SInt_16*)&(*out)[i] > *(SInt_16*)out->GetPeak()) out->SetPeak(sizeof(SInt_16), &(*out)[i]); } else if (byteDepth == 3) { *(SInt_16*)&(*out)[i + 1] = dataSer.Read(); (*out)[i] = dataSer.Read(); SInt_32 signal = 0; signal |= (*out)[i]; signal |= (*out)[i + 1] << 8; signal |= (*out)[i + 2] << 16; SInt_32 peak = 0; peak |= out->GetPeak()[0]; peak |= out->GetPeak()[1] << 8; peak |= out->GetPeak()[2] << 16; if (signal > peak) out->SetPeak(3, &(*out)[i]); } else if (byteDepth == 4 && compression == 0x3) { *(float*)&(*out)[i] = dataSer.Read(); if (*(float*)&(*out)[i] > *(float*)out->GetPeak()) out->SetPeak(sizeof(float), &(*out)[i]); } else if (byteDepth == 4) { *(SInt_32*)&(*out)[i] = dataSer.Read(); if (*(SInt_32*)&(*out)[i] > *(SInt_32*)out->GetPeak()) out->SetPeak(sizeof(SInt_32), &(*out)[i]); } else if (byteDepth == 8) { *(SInt_64*)&(*out)[i] = dataSer.Read(); if (*(SInt_64*)&(*out)[i] > *(SInt_64*)out->GetPeak()) out->SetPeak(sizeof(SInt_64), &(*out)[i]); } } return true; } }