mirror of
https://github.com/Dongyifengs/AssetStudio-Genshin-MoYi.git
synced 2025-04-22 20:49:18 +08:00
192 lines
7.0 KiB
C#
192 lines
7.0 KiB
C#
using FMOD;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace AssetStudio
|
|
{
|
|
public class AudioClipConverter
|
|
{
|
|
private AudioClip m_AudioClip;
|
|
|
|
public AudioClipConverter(AudioClip audioClip)
|
|
{
|
|
m_AudioClip = audioClip;
|
|
}
|
|
|
|
public byte[] ConvertToWav()
|
|
{
|
|
var m_AudioData = m_AudioClip.m_AudioData.GetData();
|
|
if (m_AudioData == null || m_AudioData.Length == 0)
|
|
return null;
|
|
var exinfo = new CREATESOUNDEXINFO();
|
|
var result = Factory.System_Create(out var system);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
result = system.init(1, INITFLAGS.NORMAL, IntPtr.Zero);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
exinfo.cbsize = Marshal.SizeOf(exinfo);
|
|
exinfo.length = (uint)m_AudioClip.m_Size;
|
|
result = system.createSound(m_AudioData, MODE.OPENMEMORY, ref exinfo, out var sound);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
result = sound.getNumSubSounds(out var numsubsounds);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
byte[] buff;
|
|
if (numsubsounds > 0)
|
|
{
|
|
result = sound.getSubSound(0, out var subsound);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
buff = SoundToWav(subsound);
|
|
subsound.release();
|
|
}
|
|
else
|
|
{
|
|
buff = SoundToWav(sound);
|
|
}
|
|
sound.release();
|
|
system.release();
|
|
return buff;
|
|
}
|
|
|
|
public byte[] SoundToWav(Sound sound)
|
|
{
|
|
var result = sound.getFormat(out _, out _, out int channels, out int bits);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
result = sound.getDefaults(out var frequency, out _);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
var sampleRate = (int)frequency;
|
|
result = sound.getLength(out var length, TIMEUNIT.PCMBYTES);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
result = sound.@lock(0, length, out var ptr1, out var ptr2, out var len1, out var len2);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
byte[] buffer = new byte[len1 + 44];
|
|
//添加wav头
|
|
Encoding.UTF8.GetBytes("RIFF").CopyTo(buffer, 0);
|
|
BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4);
|
|
Encoding.UTF8.GetBytes("WAVEfmt ").CopyTo(buffer, 8);
|
|
BitConverter.GetBytes(16).CopyTo(buffer, 16);
|
|
BitConverter.GetBytes((short)1).CopyTo(buffer, 20);
|
|
BitConverter.GetBytes((short)channels).CopyTo(buffer, 22);
|
|
BitConverter.GetBytes(sampleRate).CopyTo(buffer, 24);
|
|
BitConverter.GetBytes(sampleRate * channels * bits / 8).CopyTo(buffer, 28);
|
|
BitConverter.GetBytes((short)(channels * bits / 8)).CopyTo(buffer, 32);
|
|
BitConverter.GetBytes((short)bits).CopyTo(buffer, 34);
|
|
Encoding.UTF8.GetBytes("data").CopyTo(buffer, 36);
|
|
BitConverter.GetBytes(len1).CopyTo(buffer, 40);
|
|
Marshal.Copy(ptr1, buffer, 44, (int)len1);
|
|
result = sound.unlock(ptr1, ptr2, len1, len2);
|
|
if (result != RESULT.OK)
|
|
return null;
|
|
return buffer;
|
|
}
|
|
|
|
public string GetExtensionName()
|
|
{
|
|
if (m_AudioClip.version[0] < 5)
|
|
{
|
|
switch (m_AudioClip.m_Type)
|
|
{
|
|
case FMODSoundType.ACC:
|
|
return ".m4a";
|
|
case FMODSoundType.AIFF:
|
|
return ".aif";
|
|
case FMODSoundType.IT:
|
|
return ".it";
|
|
case FMODSoundType.MOD:
|
|
return ".mod";
|
|
case FMODSoundType.MPEG:
|
|
return ".mp3";
|
|
case FMODSoundType.OGGVORBIS:
|
|
return ".ogg";
|
|
case FMODSoundType.S3M:
|
|
return ".s3m";
|
|
case FMODSoundType.WAV:
|
|
return ".wav";
|
|
case FMODSoundType.XM:
|
|
return ".xm";
|
|
case FMODSoundType.XMA:
|
|
return ".wav";
|
|
case FMODSoundType.VAG:
|
|
return ".vag";
|
|
case FMODSoundType.AUDIOQUEUE:
|
|
return ".fsb";
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
switch (m_AudioClip.m_CompressionFormat)
|
|
{
|
|
case AudioCompressionFormat.PCM:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.Vorbis:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.ADPCM:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.MP3:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.PSMVAG:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.HEVAG:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.XMA:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.AAC:
|
|
return ".m4a";
|
|
case AudioCompressionFormat.GCADPCM:
|
|
return ".fsb";
|
|
case AudioCompressionFormat.ATRAC9:
|
|
return ".fsb";
|
|
}
|
|
}
|
|
|
|
return ".AudioClip";
|
|
}
|
|
|
|
public bool IsSupport
|
|
{
|
|
get
|
|
{
|
|
if (m_AudioClip.version[0] < 5)
|
|
{
|
|
switch (m_AudioClip.m_Type)
|
|
{
|
|
case FMODSoundType.AIFF:
|
|
case FMODSoundType.IT:
|
|
case FMODSoundType.MOD:
|
|
case FMODSoundType.S3M:
|
|
case FMODSoundType.XM:
|
|
case FMODSoundType.XMA:
|
|
case FMODSoundType.AUDIOQUEUE:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (m_AudioClip.m_CompressionFormat)
|
|
{
|
|
case AudioCompressionFormat.PCM:
|
|
case AudioCompressionFormat.Vorbis:
|
|
case AudioCompressionFormat.ADPCM:
|
|
case AudioCompressionFormat.MP3:
|
|
case AudioCompressionFormat.XMA:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|