Skip to content

Commit cb7bb59

Browse files
committed
Initial
1 parent 7b14388 commit cb7bb59

File tree

126 files changed

+13766
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+13766
-0
lines changed

Assembly-CSharp.csproj

Lines changed: 186 additions & 0 deletions
Large diffs are not rendered by default.

Assets/Resources/soundfonts/LICENSE_TimGM6mb.txt

Lines changed: 339 additions & 0 deletions
Large diffs are not rendered by default.
3.13 MB
Binary file not shown.
5.69 MB
Binary file not shown.
742 Bytes
Binary file not shown.

Assets/Scripts/Midi/MidiPlayer.cs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using UnityEngine;
2+
using System.IO;
3+
using System.Collections;
4+
using AudioSynthesis;
5+
using AudioSynthesis.Bank;
6+
using AudioSynthesis.Synthesis;
7+
using AudioSynthesis.Sequencer;
8+
using AudioSynthesis.Midi;
9+
using System;
10+
using System.Collections.Generic;
11+
12+
namespace UnityMidi
13+
{
14+
[RequireComponent(typeof(AudioSource))]
15+
public class MidiPlayer : MonoBehaviour
16+
{
17+
public string banksourcefile = "soundfonts/Scc1t2.sf2";
18+
[SerializeField] StreamingAssetResouce midiSource;
19+
[SerializeField] bool loadOnAwake = true;
20+
[SerializeField] bool loop = true;
21+
[SerializeField] bool playOnStart = true;
22+
[SerializeField] int channel = 2;
23+
[SerializeField] int sampleRate = 44100;
24+
[SerializeField] int bufferSize = 1024;
25+
PatchBank bank;
26+
MidiFile midi;
27+
Synthesizer synthesizer;
28+
AudioSource audioSource;
29+
MidiFileSequencer sequencer;
30+
int bufferHead = 0;
31+
float[] currentBuffer;
32+
33+
public AudioSource AudioSource { get { return audioSource; } }
34+
35+
public MidiFileSequencer Sequencer { get { return sequencer; } }
36+
37+
public PatchBank Bank { get { return bank; } }
38+
39+
public MidiFile MidiFile { get { return midi; } }
40+
41+
public void Awake()
42+
{
43+
synthesizer = new Synthesizer(sampleRate, channel, bufferSize, 1);
44+
sequencer = new MidiFileSequencer(synthesizer);
45+
audioSource = GetComponent<AudioSource>();
46+
47+
if (loadOnAwake)
48+
{
49+
LoadBank();
50+
LoadMidi(new MidiFile(midiSource));
51+
}
52+
}
53+
54+
public void Start()
55+
{
56+
if (playOnStart)
57+
{
58+
Play();
59+
}
60+
}
61+
62+
public void LoadBank()
63+
{
64+
LoadBank(new PatchBank(banksourcefile));
65+
}
66+
67+
public void LoadBank(PatchBank bank)
68+
{
69+
this.bank = bank;
70+
synthesizer.UnloadBank();
71+
synthesizer.LoadBank(bank);
72+
}
73+
74+
public void StreamMidi (byte[] Midisong)
75+
{
76+
LoadMidi(new MidiFile(Midisong));
77+
Play();
78+
}
79+
public void LoadMidi(MidiFile midi)
80+
{
81+
this.midi = midi;
82+
sequencer.Stop();
83+
sequencer.UnloadMidi();
84+
sequencer.LoadMidi(midi);
85+
}
86+
87+
public void Play()
88+
{
89+
audioSource.clip = AudioClip.Create("Midi", bufferSize, channel, sampleRate, true, OnAudioRead);
90+
audioSource.Play();
91+
sequencer.Play();
92+
}
93+
94+
public void Stop()
95+
{
96+
audioSource.Stop();
97+
sequencer.Stop();
98+
sequencer.ResetMidi();
99+
sequencer.UnloadMidi();
100+
}
101+
102+
void FillBuffer()
103+
{
104+
sequencer.FillMidiEventQueue(loop);
105+
synthesizer.GetNext();
106+
currentBuffer = synthesizer.WorkingBuffer;
107+
bufferHead = 0;
108+
}
109+
110+
void OnAudioRead(float[] data)
111+
{
112+
int count = 0;
113+
114+
while (count < data.Length)
115+
{
116+
if (currentBuffer == null)
117+
FillBuffer();
118+
else if (bufferHead >= currentBuffer.Length)
119+
FillBuffer();
120+
var length = Mathf.Min(currentBuffer.Length - bufferHead, data.Length - count);
121+
Array.Copy(currentBuffer, bufferHead, data, count, length);
122+
bufferHead += length;
123+
count += length;
124+
}
125+
}
126+
}
127+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2014 Alex Veltsistas
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
C# Digital Audio Synth
2+
Version 1.2
3+
Copyright Alex Veltsistas 2014
4+
5+
To view the source open the 'Source' folder. Additionally there is a demo called DirectSoundDemo which should help you get started.
6+
If you want to begin using the library in your own project the file AudioSynthesis.dll has already been built in release mode and is ready to be referenced.
7+
8+
9+
Whats New
10+
11+
- Moved project to visual studio 2013
12+
- converted solution to portable library
13+
- resources now handled indirectly via streams (IResource interface, see MyFile.cs for sample implementation)
14+
15+
- Fixed midi parameters
16+
- hold pedal issue resolved (hold pedal now only effects the channel its on instead of all channels)
17+
- added parameter for legato pedal (for future use, I havent decided how to implement it yet)
18+
- volume cc is no longer realtime (this follows gm spec)
19+
- fixed reset cc message (before it reset some controllers that were not supposed to be)
20+
- fixed issue with loading midis with invalid tracks
21+
22+
- Fixed SF2
23+
- added support for some initial modulators (mostly volume)
24+
- fixed issue with initial attenuation which caused some instruments to play very loud
25+
- fixed issue with volume envelope (it now operates directly in dB)
26+
27+
- Other tweaks and fixes
28+
- sample assets are now stored at their native bit depth to save memory (eg. 16bit audio stored using 16bits instead of 32)
29+
- removed various allocations in voice processing loop
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System.IO;
2+
using System.Collections.Generic;
3+
using AudioSynthesis.Wave;
4+
5+
namespace AudioSynthesis.Bank
6+
{
7+
public class AssetManager
8+
{
9+
private List<PatchAsset> patchAssets;
10+
private List<SampleDataAsset> sampleAssets;
11+
12+
public List<PatchAsset> PatchAssetList
13+
{
14+
get { return patchAssets; }
15+
}
16+
public List<SampleDataAsset> SampleAssetList
17+
{
18+
get { return sampleAssets; }
19+
}
20+
21+
public AssetManager()
22+
{
23+
patchAssets = new List<PatchAsset>();
24+
sampleAssets = new List<SampleDataAsset>();
25+
}
26+
public PatchAsset FindPatch(string name)
27+
{
28+
for (int x = 0; x < patchAssets.Count; x++)
29+
{
30+
if (patchAssets[x].Name.Equals(name))
31+
return patchAssets[x];
32+
}
33+
return null;
34+
}
35+
public SampleDataAsset FindSample(string name)
36+
{
37+
for (int x = 0; x < sampleAssets.Count; x++)
38+
{
39+
if (sampleAssets[x].Name.Equals(name))
40+
return sampleAssets[x];
41+
}
42+
return null;
43+
}
44+
//public void LoadSampleAsset(string assetName, string patchName, string directory)
45+
//{
46+
// string assetNameWithoutExtension;
47+
// string extension;
48+
// if (Path.HasExtension(assetName))
49+
// {
50+
// assetNameWithoutExtension = Path.GetFileNameWithoutExtension(assetName);
51+
// extension = Path.GetExtension(assetName).ToLower();
52+
// }
53+
// else
54+
// {
55+
// assetNameWithoutExtension = assetName;
56+
// assetName += ".wav"; //assume .wav
57+
// extension = ".wav";
58+
// }
59+
// if (FindSample(assetNameWithoutExtension) == null)
60+
// {
61+
// string waveAssetPath;
62+
// if (CrossPlatformHelper.ResourceExists(assetName))
63+
// waveAssetPath = assetName; //ex. "asset.wav"
64+
// else if (CrossPlatformHelper.ResourceExists(directory + Path.DirectorySeparatorChar + assetName))
65+
// waveAssetPath = directory + Path.DirectorySeparatorChar + assetName; //ex. "C:\asset.wav"
66+
// else if (CrossPlatformHelper.ResourceExists(directory + "/SAMPLES/" + assetName))
67+
// waveAssetPath = directory + "/SAMPLES/" + assetName; //ex. "C:\SAMPLES\asset.wav"
68+
// else if (CrossPlatformHelper.ResourceExists(directory + Path.DirectorySeparatorChar + patchName + Path.DirectorySeparatorChar + assetName))
69+
// waveAssetPath = directory + Path.DirectorySeparatorChar + patchName + Path.DirectorySeparatorChar + assetName; //ex. "C:\Piano\asset.wav"
70+
// else
71+
// throw new IOException("Could not find sample asset: (" + assetName + ") required for patch: " + patchName);
72+
// using (BinaryReader reader = new BinaryReader(CrossPlatformHelper.OpenResource(waveAssetPath)))
73+
// {
74+
// switch (extension)
75+
// {
76+
// case ".wav":
77+
// sampleAssets.Add(new SampleDataAsset(assetNameWithoutExtension, WaveFileReader.ReadWaveFile(reader)));
78+
// break;
79+
// }
80+
// }
81+
// }
82+
//}
83+
}
84+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace AudioSynthesis.Bank.Components.Effects
2+
{
3+
/// <summary>
4+
/// A simple single layer chorus that works for both mono and stereo input.
5+
/// </summary>
6+
public class Chorus : Flanger
7+
{
8+
public Chorus(int sampleRate, double minDelay, double maxDelay)
9+
:base(sampleRate,minDelay,maxDelay)
10+
{
11+
12+
}
13+
}
14+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
namespace AudioSynthesis.Bank.Components.Effects
2+
{
3+
using System;
4+
5+
public class Delay : IAudioEffect
6+
{
7+
private float[] buffer1;
8+
private float[] buffer2;
9+
private int position1;
10+
private int position2;
11+
12+
public Delay(int sampleRate, double delay)
13+
{
14+
buffer1 = new float[(int)(sampleRate * delay)];
15+
position1 = 0;
16+
}
17+
public Delay(int sampleRate, double delay1, double delay2)
18+
{
19+
buffer1 = new float[(int)(sampleRate * delay1)];
20+
position1 = 0;
21+
buffer2 = new float[(int)(sampleRate * delay2)];
22+
position2 = 0;
23+
}
24+
public void ApplyEffect(float[] source)
25+
{
26+
int x = 0, end = buffer1.Length - 1;
27+
while (x < source.Length)
28+
{
29+
if (source.Length - x >= end)
30+
{
31+
while (position1 < end)
32+
{
33+
buffer1[position1++] = source[x];
34+
source[x++] = buffer1[position1];
35+
}
36+
buffer1[position1] = source[x];
37+
position1 = 0;
38+
source[x++] = buffer1[position1];
39+
}
40+
else
41+
{
42+
while (x < source.Length)
43+
{
44+
buffer1[position1++] = source[x];
45+
source[x++] = buffer1[position1];
46+
}
47+
}
48+
}
49+
}
50+
public void ApplyEffect(float[] source1, float[] source2)
51+
{
52+
int x, end;
53+
//source1
54+
x = 0;
55+
end = buffer1.Length - 1;
56+
while (x < source1.Length)
57+
{
58+
if (source1.Length - x >= end)
59+
{
60+
while (position1 < end)
61+
{
62+
buffer1[position1++] = source1[x];
63+
source1[x++] = buffer1[position1];
64+
}
65+
buffer1[position1] = source1[x];
66+
position1 = 0;
67+
source1[x++] = buffer1[position1];
68+
}
69+
else
70+
{
71+
while (x < source1.Length)
72+
{
73+
buffer1[position1++] = source1[x];
74+
source1[x++] = buffer1[position1];
75+
}
76+
}
77+
}
78+
//source2
79+
x = 0;
80+
end = buffer2.Length - 1;
81+
while (x < source2.Length)
82+
{
83+
if (source2.Length - x >= end)
84+
{
85+
while (position2 < end)
86+
{
87+
buffer2[position2++] = source2[x];
88+
source2[x++] = buffer2[position2];
89+
}
90+
buffer2[position2] = source2[x];
91+
position2 = 0;
92+
source2[x++] = buffer2[position2];
93+
}
94+
else
95+
{
96+
while (x < source2.Length)
97+
{
98+
buffer2[position2++] = source2[x];
99+
source2[x++] = buffer2[position2];
100+
}
101+
}
102+
}
103+
}
104+
public void Reset()
105+
{
106+
position1 = 0;
107+
position2 = 0;
108+
Array.Clear(buffer1, 0, buffer1.Length);
109+
if(buffer2 != null)
110+
Array.Clear(buffer2, 0, buffer2.Length);
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)