音频解决

This commit is contained in:
sin365 2025-02-18 13:21:54 +08:00
parent a096ca21c8
commit d30a4e1d9c
2 changed files with 265 additions and 39 deletions

View File

@ -44,9 +44,9 @@ public class Essgeeinit : MonoBehaviour
uegResources = new UEGResources(); uegResources = new UEGResources();
uegLog = new UEGLog(); uegLog = new UEGLog();
InitAll(uegResources, Application.persistentDataPath); InitAll(uegResources, Application.persistentDataPath);
LoadAndRunCartridge("G:/psjapa.sms"); //LoadAndRunCartridge("G:/psjapa.sms");
//LoadAndRunCartridge("G:/Ninja_Gaiden_(UE)_type_A_[!].sms"); //LoadAndRunCartridge("G:/Ninja_Gaiden_(UE)_type_A_[!].sms");
//LoadAndRunCartridge("G:/SML2.gb"); LoadAndRunCartridge("G:/SML2.gb");
} }
void OnDisable() void OnDisable()

View File

@ -1,26 +1,60 @@
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer
{ {
[SerializeField] [SerializeField]
private AudioSource m_as; private AudioSource m_as;
private RingBuffer<float> _buffer = new RingBuffer<float>(4096); private RingBuffer<float> _buffer = new RingBuffer<float>(44100*2);
private TimeSpan lastElapsed; private TimeSpan lastElapsed;
public double audioFPS { get; private set; } public double audioFPS { get; private set; }
public bool IsRecording { get; private set; }
float lastData = 0; float lastData = 0;
private AudioClip audioClip;
private int writePos = 0;
private float[] buffer;
void Awake() void Start()
{ {
AudioClip dummy = AudioClip.Create("dummy", 1, 2, AudioSettings.outputSampleRate, false); GetComponent<AudioSource>().PlayOneShot(audioClip);
//AudioClip dummy = AudioClip.Create("dummy", 1, 2, 44100, false);
dummy.SetData(new float[] { 1, 1 }, 0);
m_as.clip = dummy;
m_as.loop = true;
m_as.spatialBlend = 1;
} }
private Queue<float> sampleQueue = new Queue<float>();
// 外部填充数据
public void AddData(float[] data)
{
lock (sampleQueue)
{
foreach (var sample in data)
{
sampleQueue.Enqueue(sample);
}
}
}
// Unity 音频线程回调
void OnAudioFilterRead(float[] data, int channels)
{
lock (sampleQueue)
{
for (int i = 0; i < data.Length; i++)
{
if (sampleQueue.Count > 0)
data[i] = sampleQueue.Dequeue();
else
data[i] = 0; // 无数据时静音
}
}
}
public void Initialize() public void Initialize()
{ {
if (!m_as.isPlaying) if (!m_as.isPlaying)
@ -37,25 +71,6 @@ public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer
} }
} }
void OnAudioFilterRead(float[] data, int channels)
{
if (!Essgeeinit.bInGame) return;
int step = channels;
for (int i = 0; i < data.Length; i += step)
{
float rawFloat = lastData;
if (_buffer.TryRead(out float rawData))
{
rawFloat = rawData;
}
data[i] = rawFloat;
for (int fill = 1; fill < step; fill++)
data[i + fill] = rawFloat;
lastData = rawFloat;
}
}
public unsafe void SubmitSamples(short* buffer, short*[] ChannelSamples, int samples_a) public unsafe void SubmitSamples(short* buffer, short*[] ChannelSamples, int samples_a)
{ {
var current = Essgeeinit.sw.Elapsed; var current = Essgeeinit.sw.Elapsed;
@ -63,22 +78,30 @@ public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer
lastElapsed = current; lastElapsed = current;
audioFPS = 1d / delta.TotalSeconds; audioFPS = 1d / delta.TotalSeconds;
//for (int i = 0; i < samples_a; i += 1)
//for (int i = 0; i < samples_a; i++)
//{ //{
// short left = BitConverter.ToInt16(buffer, i * 2 * 2); // //_buffer.Write(((i % 2 == 0)?-1:1) * buffer[i] / 32767.0f);
// //short right = BitConverter.ToInt16(buffer, i * 2 * 2 + 2); // _buffer.Write(buffer[i] / 32767.0f);
// _buffer.Write(left / 32767.0f);
// //_buffer.Write(right / 32767.0f);
//} //}
for (int i = 0; i < samples_a; i += 2) AddData(ConvertShortToFloat(buffer, samples_a));
{
_buffer.Write(buffer[i] / 32767.0f);
//_buffer.Write(buffer[i] / 32767.0f);
}
}
if (IsRecording)
{
dataChunk.AddSampleData(buffer, samples_a);
waveHeader.FileLength += (uint)samples_a;
}
}
unsafe float[] ConvertShortToFloat(short* input,int length)
{
float[] output = new float[length];
for (int i = 0; i < length; i++)
{
output[i] = input[i] / 32768.0f;
}
return output;
}
public void BufferWirte(int Off, byte[] Data) public void BufferWirte(int Off, byte[] Data)
{ {
} }
@ -96,4 +119,207 @@ public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer
return; return;
m_as.volume = Vol; m_as.volume = Vol;
} }
void Update()
{
if (Input.GetKeyDown(KeyCode.F3))
{
BeginRecording();
Debug.Log("录制");
}
if (Input.GetKeyDown(KeyCode.F4))
{
SaveRecording("D:/1.wav");
Debug.Log("保存");
}
}
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);
}
public unsafe void AddSampleData(short* stereoBuffer,int lenght)
{
for (int i = 0; i < lenght; i++)
{
WaveData.Add(stereoBuffer[i]);
}
ChunkSize += (uint)(lenght * 2);
}
}
} }