private LinkedList <float[]> generateAudioSamples() { MyMMLSequencer seq = station.acgState.sequencer; MyMixer mix = station.acgState.mixer; List <MySynthesizer> sss = station.acgState.synthesizers; if ((seq == null) || (mix == null) || (sss == null)) { return(null); } mix.Reset(); for (int j = 0; j < sss.Count; j++) { seq.SetSynthesizer(j, sss[j], toneSet, toneMap, 0xffffffffU); } seq.KeyShift = clip.Key; seq.VolumeScale = clip.Volume; seq.TempoScale = clip.Tempo; seq.Play(mml, 0.0f, false); LinkedList <float[]> temp = new LinkedList <float[]>(); const int workSize = 4096; float[] work = new float[workSize * AudioClipGeneratorState.numChannels]; bool zeroCross = false; for (;;) { if (station.disabled) { return(null); } if (seq.Playing) { mix.Update(); } Array.Clear(work, 0, work.Length); int numSamples = mix.Output(work, AudioClipGeneratorState.numChannels, workSize); if (numSamples == 0) { if (!zeroCross) { mix.Update(); continue; } break; } { float[] block = new float[numSamples * AudioClipGeneratorState.numChannels]; Array.Copy(work, block, numSamples * AudioClipGeneratorState.numChannels); temp.AddLast(block); float v0 = work[(numSamples - 1) * AudioClipGeneratorState.numChannels + 0]; float v1 = work[(numSamples - 1) * AudioClipGeneratorState.numChannels + 1]; zeroCross = (v0 == 0.0f) && (v1 == 0.0f); } } return(temp); }
public AudioClip CreateAudioClip(string name, MyMMLSequence mml, List <object> toneSet, Dictionary <int, int> toneMap) { const int frequency = 44100; const int numChannels = 2; MyMixer mix = new MyMixer(frequency, true); MySynthesizer ss0 = new MySynthesizerPM8(mix); MyMMLSequencer seq = new MyMMLSequencer(mix.TickFrequency); mix.TickCallback = () => seq.Tick(); seq.SetSynthesizer(0, ss0, toneSet, toneMap, 0xffffffffU); seq.Play(mml, 0.0f, false); int totalSamples = 0; LinkedList <float[]> temp = new LinkedList <float[]>(); const int workSize = 4096; float[] work = new float[workSize * numChannels]; bool first = true; for (;;) { Array.Clear(work, 0, work.Length); if (seq.Playing) { mix.Update(); } int numSamples = mix.Output(work, numChannels, workSize); if (numSamples == 0) { break; } if (first) { // skip leading zeros. for (var i = 0; i < numSamples; i++) { if ((work[i * 2 + 0] != 0.0f) || (work[i * 2 + 1] != 0.0f)) { first = false; numSamples -= i; float[] block = new float[numSamples * numChannels]; Array.Copy(work, i * 2, block, 0, numSamples * numChannels); temp.AddLast(block); break; } } } else { float[] block = new float[numSamples * numChannels]; Array.Copy(work, block, numSamples * numChannels); temp.AddLast(block); } totalSamples += numSamples; } AudioClip clip = AudioClip.Create(name, totalSamples, numChannels, frequency, false); int pos = 0; foreach (var block in temp) { clip.SetData(block, pos); pos += block.Length / numChannels; } ss0.Terminate(); mix.Terminate(); return(clip); }