Essgee.Unity/Assets/Scripts/UEssgeeInterface/UEGSoundPlayer.cs

309 lines
8.3 KiB
C#
Raw Permalink Normal View History

using System;
2025-02-18 13:21:54 +08:00
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
2025-01-03 01:07:11 +08:00
using UnityEngine;
public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer
{
[SerializeField]
private AudioSource m_as;
2025-02-18 17:44:30 +08:00
private RingBuffer<float> _buffer = new RingBuffer<float>(44100 * 2);
private TimeSpan lastElapsed;
public double audioFPS { get; private set; }
2025-02-18 13:21:54 +08:00
public bool IsRecording { get; private set; }
2025-02-18 17:44:30 +08:00
void Awake()
{
2025-02-18 17:44:30 +08:00
// <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
AudioConfiguration config = AudioSettings.GetConfiguration();
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
config.sampleRate = 44100; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 44100Hz
config.numRealVoices = 32; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƵԴ<C6B5><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
config.numVirtualVoices = 512; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƵԴ<C6B5><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
config.dspBufferSize = 1024; // <20><><EFBFBD><EFBFBD> DSP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
config.speakerMode = AudioSpeakerMode.Stereo; // <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Ӧ<><D3A6><EFBFBD>µ<EFBFBD><C2B5><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
if (AudioSettings.Reset(config))
{
Debug.Log("Audio settings updated successfully.");
Debug.Log("Sample Rate: " + config.sampleRate + "Hz");
Debug.Log("Speaker Mode: " + config.speakerMode);
}
else
{
Debug.LogError("Failed to update audio settings.");
}
}
2025-01-03 01:07:11 +08:00
2025-02-18 13:21:54 +08:00
private Queue<float> sampleQueue = new Queue<float>();
2025-01-03 01:07:11 +08:00
2025-02-18 13:21:54 +08:00
// Unity <20><>Ƶ<EFBFBD>̻߳ص<CCBB>
void OnAudioFilterRead(float[] data, int channels)
{
2025-02-18 17:44:30 +08:00
for (int i = 0; i < data.Length; i++)
{
2025-02-18 17:44:30 +08:00
if (_buffer.TryRead(out float rawData))
data[i] = rawData;
else
data[i] = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
}
}
2025-01-03 01:07:11 +08:00
2025-02-18 13:21:54 +08:00
public void Initialize()
{
2025-02-18 13:21:54 +08:00
if (!m_as.isPlaying)
{
2025-02-18 13:21:54 +08:00
m_as.Play();
}
}
2025-01-03 01:07:11 +08:00
2025-02-18 13:21:54 +08:00
public void StopPlay()
{
if (m_as.isPlaying)
{
m_as.Stop();
}
}
2025-01-03 01:07:11 +08:00
2025-02-08 10:12:58 +08:00
public unsafe void SubmitSamples(short* buffer, short*[] ChannelSamples, int samples_a)
2025-01-03 01:07:11 +08:00
{
var current = Essgeeinit.sw.Elapsed;
var delta = current - lastElapsed;
lastElapsed = current;
audioFPS = 1d / delta.TotalSeconds;
2025-01-03 01:07:11 +08:00
2025-02-18 17:44:30 +08:00
for (int i = 0; i < samples_a; i += 1)
{
2025-02-18 17:44:30 +08:00
_buffer.Write(buffer[i] / 32767.0f);
2025-02-18 13:21:54 +08:00
}
}
2025-01-03 01:07:11 +08:00
public void BufferWirte(int Off, byte[] Data)
{
}
public void GetCurrentPosition(out int play_position, out int write_position)
{
play_position = 0;
write_position = 0;
}
public void SetVolume(int Vol)
{
//TODO <20><><EFBFBD><EFBFBD>
if (m_as)
return;
m_as.volume = Vol;
2025-01-03 01:07:11 +08:00
}
2025-02-18 13:21:54 +08:00
void Update()
{
if (Input.GetKeyDown(KeyCode.F3))
{
BeginRecording();
Debug.Log(<><C2BC>");
}
if (Input.GetKeyDown(KeyCode.F4))
{
SaveRecording("D:/1.wav");
Debug.Log("<22><><EFBFBD><EFBFBD>");
}
}
WaveHeader waveHeader;
FormatChunk formatChunk;
DataChunk dataChunk;
public void BeginRecording()
{
waveHeader = new WaveHeader();
formatChunk = new FormatChunk(44100, 2);
dataChunk = new DataChunk();
waveHeader.FileLength += formatChunk.Length();
IsRecording = true;
}
public void SaveRecording(string filename)
{
using (FileStream file = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
file.Write(waveHeader.GetBytes(), 0, (int)waveHeader.Length());
file.Write(formatChunk.GetBytes(), 0, (int)formatChunk.Length());
file.Write(dataChunk.GetBytes(), 0, (int)dataChunk.Length());
}
IsRecording = false;
}
class WaveHeader
{
const string fileTypeId = "RIFF";
const string mediaTypeId = "WAVE";
public string FileTypeId { get; private set; }
public uint FileLength { get; set; }
public string MediaTypeId { get; private set; }
public WaveHeader()
{
FileTypeId = fileTypeId;
MediaTypeId = mediaTypeId;
FileLength = 4; /* Minimum size is always 4 bytes */
}
public byte[] GetBytes()
{
List<byte> chunkData = new List<byte>();
chunkData.AddRange(Encoding.ASCII.GetBytes(FileTypeId));
chunkData.AddRange(BitConverter.GetBytes(FileLength));
chunkData.AddRange(Encoding.ASCII.GetBytes(MediaTypeId));
return chunkData.ToArray();
}
public uint Length()
{
return (uint)GetBytes().Length;
}
}
class FormatChunk
{
const string chunkId = "fmt ";
ushort bitsPerSample, channels;
uint frequency;
public string ChunkId { get; private set; }
public uint ChunkSize { get; private set; }
public ushort FormatTag { get; private set; }
public ushort Channels
{
get { return channels; }
set { channels = value; RecalcBlockSizes(); }
}
public uint Frequency
{
get { return frequency; }
set { frequency = value; RecalcBlockSizes(); }
}
public uint AverageBytesPerSec { get; private set; }
public ushort BlockAlign { get; private set; }
public ushort BitsPerSample
{
get { return bitsPerSample; }
set { bitsPerSample = value; RecalcBlockSizes(); }
}
public FormatChunk()
{
ChunkId = chunkId;
ChunkSize = 16;
FormatTag = 1; /* MS PCM (Uncompressed wave file) */
Channels = 2; /* Default to stereo */
Frequency = 44100; /* Default to 44100hz */
BitsPerSample = 16; /* Default to 16bits */
RecalcBlockSizes();
}
public FormatChunk(int frequency, int channels) : this()
{
Channels = (ushort)channels;
Frequency = (ushort)frequency;
RecalcBlockSizes();
}
private void RecalcBlockSizes()
{
BlockAlign = (ushort)(channels * (bitsPerSample / 8));
AverageBytesPerSec = frequency * BlockAlign;
}
public byte[] GetBytes()
{
List<byte> chunkBytes = new List<byte>();
chunkBytes.AddRange(Encoding.ASCII.GetBytes(ChunkId));
chunkBytes.AddRange(BitConverter.GetBytes(ChunkSize));
chunkBytes.AddRange(BitConverter.GetBytes(FormatTag));
chunkBytes.AddRange(BitConverter.GetBytes(Channels));
chunkBytes.AddRange(BitConverter.GetBytes(Frequency));
chunkBytes.AddRange(BitConverter.GetBytes(AverageBytesPerSec));
chunkBytes.AddRange(BitConverter.GetBytes(BlockAlign));
chunkBytes.AddRange(BitConverter.GetBytes(BitsPerSample));
return chunkBytes.ToArray();
}
public uint Length()
{
return (uint)GetBytes().Length;
}
}
class DataChunk
{
const string chunkId = "data";
public string ChunkId { get; private set; }
public uint ChunkSize { get; set; }
public List<short> WaveData { get; private set; }
public DataChunk()
{
ChunkId = chunkId;
ChunkSize = 0;
WaveData = new List<short>();
}
public byte[] GetBytes()
{
List<byte> chunkBytes = new List<byte>();
chunkBytes.AddRange(Encoding.ASCII.GetBytes(ChunkId));
chunkBytes.AddRange(BitConverter.GetBytes(ChunkSize));
byte[] bufferBytes = new byte[WaveData.Count * 2];
Buffer.BlockCopy(WaveData.ToArray(), 0, bufferBytes, 0, bufferBytes.Length);
chunkBytes.AddRange(bufferBytes.ToList());
return chunkBytes.ToArray();
}
public uint Length()
{
return (uint)GetBytes().Length;
}
public void AddSampleData(short[] stereoBuffer)
{
WaveData.AddRange(stereoBuffer);
ChunkSize += (uint)(stereoBuffer.Length * 2);
}
2025-02-18 17:44:30 +08:00
public unsafe void AddSampleData(short* stereoBuffer, int lenght)
2025-02-18 13:21:54 +08:00
{
for (int i = 0; i < lenght; i++)
{
WaveData.Add(stereoBuffer[i]);
}
ChunkSize += (uint)(lenght * 2);
}
}
2025-01-03 01:07:11 +08:00
}