流式音频采用DSP实现,VideoProvider和audioProvider改为monobehaviour
This commit is contained in:
parent
b8386bb3c9
commit
4644b7022f
@ -25,7 +25,5 @@ namespace MyNes.Core
|
||||
void SignalToggle(bool started);
|
||||
|
||||
void SetVolume(int Vol);
|
||||
|
||||
void Update();
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,5 @@ namespace MyNes.Core
|
||||
void ToggleFPS(bool show_fps);
|
||||
|
||||
void ApplyFilter();
|
||||
|
||||
void Update();
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace MyNes.Core
|
||||
|
||||
public static WaveRecorder WaveRecorder { get; private set; }
|
||||
|
||||
public static void Initialize(IFileManager fileManager)
|
||||
public static void Initialize(IFileManager fileManager, IVideoProvider videoProvider, IAudioProvider audioProvider)
|
||||
{
|
||||
Tracer.WriteLine("Initializing My Nes Core ....");
|
||||
FileManager = fileManager;
|
||||
@ -42,6 +42,8 @@ namespace MyNes.Core
|
||||
.GetAssemblies()
|
||||
.SelectMany(ass => ass.GetTypes());
|
||||
|
||||
VideoProvider = videoProvider;
|
||||
AudioProvider = audioProvider;
|
||||
foreach (var type in allTypes)
|
||||
{
|
||||
if (type.IsSubclassOf(typeof(Board)) && !type.IsAbstract)
|
||||
@ -50,18 +52,6 @@ namespace MyNes.Core
|
||||
Boards.Add(board);
|
||||
Tracer.WriteLine("Board added: " + board.Name + " [ Mapper " + board.MapperNumber + "]");
|
||||
}
|
||||
else if (VideoProvider == null && typeof(IVideoProvider).IsAssignableFrom(type) && !type.IsAbstract)
|
||||
{
|
||||
IVideoProvider videoProvider = Activator.CreateInstance(type) as IVideoProvider;
|
||||
VideoProvider = videoProvider;
|
||||
Tracer.WriteLine("Video provider setuped: " + videoProvider.Name + " [" + videoProvider.ID + "]");
|
||||
}
|
||||
else if (typeof(IAudioProvider).IsAssignableFrom(type) && !type.IsAbstract)
|
||||
{
|
||||
IAudioProvider audioProvider = Activator.CreateInstance(type) as IAudioProvider;
|
||||
AudioProvider = audioProvider;
|
||||
Tracer.WriteLine("Audio provider setuped: " + audioProvider.Name + " [" + audioProvider.ID + "]");
|
||||
}
|
||||
}
|
||||
|
||||
Tracer.WriteInformation("Done.");
|
||||
|
@ -167,10 +167,59 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: ac8cd27a180bf3e489b2ca27c821bffe, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
AS: {fileID: 1379369699}
|
||||
DrawImage: {fileID: 730321751}
|
||||
DO: {fileID: 0}
|
||||
Fps: {fileID: 1680039028}
|
||||
VideoCom: {fileID: 0}
|
||||
AudioCom: {fileID: 0}
|
||||
--- !u!1 &455467288
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 455467291}
|
||||
- component: {fileID: 455467290}
|
||||
m_Layer: 0
|
||||
m_Name: GameObject
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &455467290
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 455467288}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 00080631f10e2834db28c37a11188a74, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
sampleRate: 44100
|
||||
channels: 2
|
||||
bufferLength: 1024
|
||||
audioClip: {fileID: 0}
|
||||
audioSource: {fileID: 0}
|
||||
audioBuffer: []
|
||||
isRunning: 1
|
||||
--- !u!4 &455467291
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 455467288}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 253.16292, y: 149.09415, z: -2.2723875}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &708549044
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -276,13 +325,14 @@ GameObject:
|
||||
- component: {fileID: 730321749}
|
||||
- component: {fileID: 730321752}
|
||||
- component: {fileID: 730321751}
|
||||
- component: {fileID: 730321753}
|
||||
m_Layer: 5
|
||||
m_Name: video
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &730321749
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -337,6 +387,19 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 730321748}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &730321753
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 730321748}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f2632911774df3c488ec24b39651c4de, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_image: {fileID: 730321751}
|
||||
--- !u!1 &786008057
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -369,7 +432,6 @@ RectTransform:
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 730321749}
|
||||
- {fileID: 1680039031}
|
||||
- {fileID: 1379369698}
|
||||
m_Father: {fileID: 258485947}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@ -611,6 +673,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1379369698}
|
||||
- component: {fileID: 1379369699}
|
||||
- component: {fileID: 1379369700}
|
||||
m_Layer: 5
|
||||
m_Name: Audio
|
||||
m_TagString: Untagged
|
||||
@ -648,7 +711,7 @@ AudioSource:
|
||||
serializedVersion: 4
|
||||
OutputAudioMixerGroup: {fileID: 0}
|
||||
m_audioClip: {fileID: 0}
|
||||
m_PlayOnAwake: 1
|
||||
m_PlayOnAwake: 0
|
||||
m_Volume: 1
|
||||
m_Pitch: 1
|
||||
Loop: 0
|
||||
@ -733,100 +796,19 @@ AudioSource:
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
--- !u!1 &1680039027
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1680039031}
|
||||
- component: {fileID: 1680039030}
|
||||
- component: {fileID: 1680039028}
|
||||
- component: {fileID: 1680039029}
|
||||
m_Layer: 5
|
||||
m_Name: fps
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1680039028
|
||||
--- !u!114 &1379369700
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1680039027}
|
||||
m_GameObject: {fileID: 1379369697}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 765129d4fad76714191795975893ea9c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 14
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 10
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 0
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: 12324234
|
||||
--- !u!114 &1680039029
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1680039027}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_HorizontalFit: 2
|
||||
m_VerticalFit: 2
|
||||
--- !u!222 &1680039030
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1680039027}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!224 &1680039031
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1680039027}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 786008058}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 1, y: 0}
|
||||
m_as: {fileID: 1379369699}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -835,3 +817,4 @@ SceneRoots:
|
||||
- {fileID: 708549046}
|
||||
- {fileID: 258485947}
|
||||
- {fileID: 1359344834}
|
||||
- {fileID: 455467291}
|
||||
|
@ -1,17 +1,11 @@
|
||||
using MyNes.Core;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using UnityEditor.PackageManager.UI;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AxibugEmuOnline.Client
|
||||
{
|
||||
public class AudioProvider : IAudioProvider
|
||||
public class AudioProvider : MonoBehaviour, IAudioProvider
|
||||
{
|
||||
public string Name => nameof(AudioProvider);
|
||||
|
||||
@ -22,47 +16,53 @@ namespace AxibugEmuOnline.Client
|
||||
public bool AllowFrequencyChange => true;
|
||||
|
||||
private bool m_isPlaying;
|
||||
|
||||
[SerializeField]
|
||||
private AudioSource m_as;
|
||||
private int samples_added;
|
||||
|
||||
|
||||
private Queue<float> _buffer = new Queue<float>();
|
||||
private Queue<short> _buffer = new Queue<short>();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
m_as = NesCoreProxy.Instance.AS;
|
||||
m_as.clip = AudioClip.Create("nes wav", 48000 * 2, 1, 48000, true, OnAudioFilterRead);
|
||||
m_as.loop = true;
|
||||
m_as.playOnAwake = false;
|
||||
m_as.spatialBlend = 0f;
|
||||
var dummy = AudioClip.Create("dummy", 1, 1, AudioSettings.outputSampleRate, false);
|
||||
|
||||
dummy.SetData(new float[] { 1 }, 0);
|
||||
m_as.clip = dummy; //just to let unity play the audiosource
|
||||
m_as.loop = true;
|
||||
m_as.spatialBlend = 1;
|
||||
m_as.Play();
|
||||
}
|
||||
|
||||
public void Update() { }
|
||||
|
||||
|
||||
private void OnAudioFilterRead(float[] data)
|
||||
void OnAudioFilterRead(float[] data, int channels)
|
||||
{
|
||||
lock (_buffer)
|
||||
while (_buffer.Count >= data.Length / 2)
|
||||
{
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] = _buffer.Count > 0 ? _buffer.Dequeue() : 0;
|
||||
}
|
||||
}
|
||||
//Thread.Sleep(10);
|
||||
break;
|
||||
}
|
||||
|
||||
int step = channels;
|
||||
for (int i = 0; i < data.Length; i += step)
|
||||
{
|
||||
var rawData = _buffer.Count > 0 ? _buffer.Dequeue() : 0;
|
||||
var rawFloat = rawData / 124f;
|
||||
data[i] = rawFloat;
|
||||
for (int fill = 1; fill < step; fill++)
|
||||
data[i + fill] = rawFloat;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int EmuAudioTimeSample = 0;
|
||||
public void SubmitSamples(ref short[] buffer, ref int samples_a)
|
||||
{
|
||||
lock (_buffer)
|
||||
EmuAudioTimeSample += samples_a;
|
||||
for (int i = 0; i < samples_a; i++)
|
||||
{
|
||||
foreach (var a in buffer.Take(samples_a).ToArray())
|
||||
{
|
||||
var floatData = (float)a / 124;
|
||||
_buffer.Enqueue(floatData);
|
||||
}
|
||||
_buffer.Enqueue(buffer[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void TogglePause(bool paused)
|
||||
|
@ -1,26 +1,30 @@
|
||||
using MyNes.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Video;
|
||||
|
||||
namespace AxibugEmuOnline.Client
|
||||
{
|
||||
public class UguiVideoProvider : IVideoProvider
|
||||
public class UguiVideoProvider : MonoBehaviour, IVideoProvider
|
||||
{
|
||||
public string Name => "Unity UI Video";
|
||||
|
||||
public string ID => nameof(UguiVideoProvider).GetHashCode().ToString();
|
||||
|
||||
private Color[] m_texRawBuffer = new Color[256 * 240];
|
||||
private Texture2D m_rawBufferWarper = new Texture2D(256, 240);
|
||||
private Texture2D m_rawBufferWarper;
|
||||
[SerializeField]
|
||||
private RawImage m_image;
|
||||
private RenderTexture m_drawRT;
|
||||
private Color temp = Color.white;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
m_image = NesCoreProxy.Instance.DrawImage;
|
||||
m_rawBufferWarper = new Texture2D(256, 240);
|
||||
m_image.texture = RenderTexture.GetTemporary(256, 240, 0, UnityEngine.Experimental.Rendering.GraphicsFormat.B8G8R8A8_UNorm);
|
||||
}
|
||||
|
||||
|
@ -7,27 +7,10 @@ namespace AxibugEmuOnline.Client.Manager
|
||||
{
|
||||
public class AppEmu : IFileManager
|
||||
{
|
||||
public IVideoProvider UguiVideo { get; private set; }
|
||||
public IAudioProvider Audio { get; private set; }
|
||||
|
||||
public void Init()
|
||||
public void Init(IVideoProvider videoCom,IAudioProvider audioCom)
|
||||
{
|
||||
MyNesMain.Initialize(this);
|
||||
NesEmu.LoadGame("E:/rzg4.nes", out var successed, true);
|
||||
UguiVideo = MyNesMain.VideoProvider;
|
||||
Audio = MyNesMain.AudioProvider;
|
||||
|
||||
var fps_nes_missle = 1.0 / 59.0;
|
||||
NesEmu.SetFramePeriod(ref fps_nes_missle);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
UguiVideo.Update();
|
||||
Audio.Update();
|
||||
|
||||
double t = Time.deltaTime;
|
||||
NesEmu.SetFramePeriod(ref t);
|
||||
MyNesMain.Initialize(this, videoCom, audioCom);
|
||||
NesEmu.LoadGame("E:/kirby.nes", out var successed, true);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -10,22 +10,15 @@ namespace AxibugEmuOnline.Client
|
||||
{
|
||||
public static NesCoreProxy Instance { get; private set; }
|
||||
|
||||
public AudioSource AS;
|
||||
public RawImage DrawImage;
|
||||
public DefaultAudioOutput DO;
|
||||
public Text Fps;
|
||||
public UguiVideoProvider VideoCom;
|
||||
public AudioProvider AudioCom;
|
||||
|
||||
private AppEmu m_appEnum = new AppEmu();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Instance = this;
|
||||
m_appEnum.Init();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
m_appEnum.Update();
|
||||
m_appEnum.Init(VideoCom, AudioCom);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
|
Loading…
Reference in New Issue
Block a user