public static void Main(string[] args) { var pinCS0 = GpioPin.FromNumber(25); // Pin 22 (BCM 25) var pinCS1 = GpioPin.FromNumber(26); // Pin 37 (BCM 26) var pinRST = GpioPin.FromNumber(16); // Pin 36 (BCM 16) var spiSettings = new SpiConnectionSettings(busId: 0, chipSelectLine: 0); var gpioPinMap = new Dictionary <TargetChip, ChipPinConfig> { [TargetChip.Board0] = new ChipPinConfig(csPin: pinCS0, resetPin: pinRST), [TargetChip.Board1] = new ChipPinConfig(csPin: pinCS1, resetPin: pinRST), }; using (var spiDevice = new UnixSpiDevice(spiSettings)) using (var gpioController = new GpioController(PinNumberingScheme.Logical)) using (var ymf825Device = new NativeSpi(spiDevice, gpioController, gpioPinMap)) { var driver = new Ymf825Driver(ymf825Device); driver.EnableSectionMode(); Console.WriteLine("Software Reset"); driver.ResetSoftware(); SetupTones(driver); var index = 0; var score = new[] { 60, 62, 64, 65, 67, 69, 71, 72, 72, 74, 76, 77, 79, 81, 83, 84, 84, 83, 81, 79, 77, 76, 74, 72, 72, 71, 69, 67, 65, 64, 62, 60 }; while (true) { const int noteOnTime = 250; const int sleepTime = 0; NoteOn(driver, score[index]); Thread.Sleep(noteOnTime); NoteOff(driver); Thread.Sleep(sleepTime); if (Console.KeyAvailable) { break; } index++; if (index >= score.Length) { index = 0; } } driver.ResetHardware(); } }
public MidiDriver(IList <ToneItem> toneItems, IList <EqualizerItem> equalizerItems, Ymf825Driver driver) { ToneItems = toneItems; EqualizerItems = equalizerItems; Driver = driver; Driver.EnableSectionMode(); for (var i = 0; i < 16; i++) { noteOnKeys[i] = -1; pitchBends[i] = 1.0; corrections[i] = 1.0; volumes[i] = 100.0 / 127.0; toneVolumes[i] = 1.0; lchVolumes[i] = 1.0; rchVolumes[i] = 1.0; expressions[i] = 1.0; rpnMsb[i] = 127; rpnLsb[i] = 127; fineTune[i] = 1.0; pitchBendWidth[i] = 2.0; } }
private void ConnectDevice() { DeviceInfo = Spi.GetDeviceInfoList()[toolStripComboBox_deviceList.SelectedIndex]; ymf825 = new CbwYmf825Bb(toolStripComboBox_deviceList.SelectedIndex); Driver = new Ymf825Driver(ymf825); ymf825.DataWrote += (sender, args) => { registerMap.SetData(args.Address, args.Data); }; ymf825.DataBurstWrote += (sender, args) => { if (args.Data.Count <= 0) { return; } if (args.Address == 0x07) { registerMap.SetData(args.Address, args.Data.Last()); var toneNumber = args.Data[0] - 0x80; if (toneNumber < 0 || toneNumber > 16 || args.Data.Count < toneNumber * 30 + 5) { Console.WriteLine($"Invalid BurstWrite Data - Tone Number: {toneNumber}, Data Size: {args.Data.Count} (required {toneNumber * 30 + 5})"); return; } for (var i = 0; i < toneNumber; i++) { for (var j = 0; j < 30; j++) { toneParameterRegisterMap[i].SetData(j, args.Data[i * 30 + j + 1]); } } } else if (args.Address >= 0x20 || args.Address <= 0x22) { var eq = args.Address - 0x20; if (args.Data.Count < 5) { return; } for (var i = 0; i < 5; i++) { registerMap.SetData(0x23 + 3 * eq + i, args.Data[i]); } } }; SpiConnected = true; Driver.ResetHardware(); Driver.ResetSoftware(); Connected?.Invoke(this, new EventArgs()); }
private void DisconnectDevice() { Driver?.ResetHardware(); Driver = null; ymf825?.Dispose(); ymf825 = null; SpiConnected = false; Disconnected?.Invoke(this, new EventArgs()); }
private void PitchBend(int channel, int data1, int data2) { var bendData = ((data2 << 7) | data1) - 8192; pitchBends[channel] = Math.Pow(Math.Pow(2.0, pitchBendWidth[channel] / 12.0), bendData / 8192.0); var correction = corrections[channel] * pitchBends[channel] * fineTune[channel]; Ymf825Driver.ConvertForFrequencyMultiplier(correction, out var integer, out var fraction); Driver.Section(() => { Driver.SetVoiceNumber(channel); Driver.SetFrequencyMultiplier(integer, fraction); }); }
private static void NoteOn(Ymf825Driver driver, int key) { Ymf825Driver.GetFnumAndBlock(key, out var fnum, out var block, out var correction); Ymf825Driver.ConvertForFrequencyMultiplier(correction, out var integer, out var fraction); var freq = Ymf825Driver.CalcFrequency(fnum, block); Console.WriteLine($"key: {key}, freq: {freq:f1} Hz, fnum: {fnum:f0}, block: {block}, correction: {correction:f3}, integer: {integer}, fraction: {fraction}"); driver.Section(() => { driver.SetVoiceNumber(0); driver.SetVoiceVolume(15); driver.SetFrequencyMultiplier(integer, fraction); driver.SetFnumAndBlock((int)Math.Round(fnum), block); driver.SetToneFlag(0, true, false, false); }); }
private void SendNoteOn(int channel, int key, int velocity) { var volume = velocity / 127.0; Ymf825Driver.GetFnumAndBlock(key, out var fnum, out var block, out var correction); corrections[channel] = correction; correction *= pitchBends[channel] * fineTune[channel]; Ymf825Driver.ConvertForFrequencyMultiplier(correction, out var integer, out var fraction); Driver.Section(() => { Driver.SetVoiceNumber(channel); Driver.SetChannelVolume((int)Math.Round(volume * 31.0), false); Driver.SetFrequencyMultiplier(integer, fraction); Driver.SetFnumAndBlock((int)Math.Round(fnum), block); Driver.SetToneFlag(channel, true, false, false); }); }
private void Rpn(int channel) { if (rpnMsb[channel] == 0 && rpnLsb[channel] == 1) { var bendData = ((dataEntryMsb[channel] << 7) | dataEntryLsb[channel]) - 8192; // precalc: Math.Pow(2.0, 2.0 / 12.0) = 1.122462048309373 fineTune[channel] = Math.Pow(Math.Pow(2.0, 2.0 / 12.0), bendData / 8192.0); var correction = corrections[channel] * pitchBends[channel] * fineTune[channel]; Ymf825Driver.ConvertForFrequencyMultiplier(correction, out var integer, out var fraction); Driver.Section(() => { Driver.SetVoiceNumber(channel); Driver.SetFrequencyMultiplier(integer, fraction); }); } if (rpnMsb[channel] == 0 && rpnLsb[channel] == 0) { pitchBendWidth[channel] = dataEntryMsb[channel]; } }
private static void SetupTones(Ymf825Driver driver) { Console.WriteLine("Tone Init"); var tones = new ToneParameterCollection { [0] = ToneParameter.GetSine() }; driver.Section(() => { driver.WriteContentsData(tones, 0); driver.SetSequencerSetting(SequencerSetting.AllKeyOff | SequencerSetting.AllMute | SequencerSetting.AllEgReset | SequencerSetting.R_FIFOR | SequencerSetting.R_SEQ | SequencerSetting.R_FIFO); }, 1); driver.Section(() => { driver.SetSequencerSetting(SequencerSetting.Reset); driver.SetToneFlag(0, false, true, true); driver.SetChannelVolume(31, true); driver.SetVibratoModuration(0); driver.SetFrequencyMultiplier(1, 0); }); }
private static void NoteOff(Ymf825Driver driver) => driver.Section(() => driver.SetToneFlag(0, false, false, false));
private static void Main() { Console.WriteLine("Image type: {0}bit", Environment.Is64BitProcess ? "64" : "32"); if (D2XxSpi.DeviceCount < 1) { return; } using (var ymf825 = SelectInterface()) { var driver = new Ymf825Driver(ymf825); driver.EnableSectionMode(); Console.WriteLine("Software Reset"); driver.ResetSoftware(); { Console.WriteLine("Tone Init"); var tones = new ToneParameterCollection { [0] = ToneParameter.GetSine() }; driver.Section(() => { driver.WriteContentsData(tones, 0); driver.SetSequencerSetting(SequencerSetting.AllKeyOff | SequencerSetting.AllMute | SequencerSetting.AllEgReset | SequencerSetting.R_FIFOR | SequencerSetting.R_SEQ | SequencerSetting.R_FIFO); }, 1); driver.Section(() => { driver.SetSequencerSetting(SequencerSetting.Reset); driver.SetToneFlag(0, false, true, true); driver.SetChannelVolume(31, true); driver.SetVibratoModuration(0); driver.SetFrequencyMultiplier(1, 0); }); } var noteon = new Action <int>(key => { Ymf825Driver.GetFnumAndBlock(key, out var fnum, out var block, out var correction); Ymf825Driver.ConvertForFrequencyMultiplier(correction, out var integer, out var fraction); var freq = Ymf825Driver.CalcFrequency(fnum, block); Console.WriteLine("key: {0}, freq: {4:f1} Hz, fnum: {5:f0}, block: {6}, correction: {1:f3}, integer: {2}, fraction: {3}", key, correction, integer, fraction, freq, fnum, block); driver.Section(() => { driver.SetVoiceNumber(0); driver.SetVoiceVolume(15); driver.SetFrequencyMultiplier(integer, fraction); driver.SetFnumAndBlock((int)Math.Round(fnum), block); driver.SetToneFlag(0, true, false, false); }); }); var noteoff = new Action(() => { driver.Section(() => driver.SetToneFlag(0, false, false, false)); }); var index = 0; var score = new[] { 60, 62, 64, 65, 67, 69, 71, 72, 72, 74, 76, 77, 79, 81, 83, 84, 84, 83, 81, 79, 77, 76, 74, 72, 72, 71, 69, 67, 65, 64, 62, 60 }; while (true) { const int noteOnTime = 250; const int sleepTime = 0; noteon(score[index]); Thread.Sleep(noteOnTime); noteoff(); Thread.Sleep(sleepTime); if (Console.KeyAvailable) { break; } index++; if (index >= score.Length) { index = 0; } } ymf825.InvokeHardwareReset(); } }
private static void Run(Options options) { const int resolution = 1000; const double tickSeconds = 1.0 / resolution; const double tickMilliSeconds = tickSeconds * 1000; var savePath = GetSavePath(options); if (File.Exists(savePath)) { File.Delete(savePath); } using (var zipArchive = ZipFile.Open(savePath, ZipArchiveMode.Create)) { using (var fileStream = zipArchive.CreateEntry("config.json", CompressionLevel.Optimal).Open()) using (var sw = new StreamWriter(fileStream)) { var config = new Dictionary <string, object> { { "version", 0 }, { "resolution", resolution } }; sw.Write(JsonConvert.SerializeObject(config)); } using (var fileStream = zipArchive.CreateEntry("dump", CompressionLevel.Optimal).Open()) using (var dumpWriter = new DumpWriter(fileStream)) { var sequence = new Sequence(options.InputFile); var sequencer = new Sequencer(sequence); var ymf825DumpChip = new Ymf825DumpChip(dumpWriter); var ymf825Driver = new Ymf825Driver(ymf825DumpChip); var project = LoadProject(options); var driver = new MidiDriver(project.Tones.ToArray(), project.Equalizers.ToArray(), ymf825Driver); var stopped = false; ymf825Driver.EnableSectionMode(); ymf825Driver.SleepAction += i => { var tick = (int)Math.Ceiling(i / tickMilliSeconds); if (dumpWriter.Disposed) { return; } dumpWriter.RealtimeWait((ushort)tick); }; driver.Start(); sequencer.OnTrackEvent += (sender, args) => { foreach (var argsEvent in args.Events) { driver.ProcessMidiEvent(argsEvent); } }; sequencer.SequenceEnd += (sender, args) => stopped = true; sequencer.Tick = 0L; while (!stopped) { sequencer.Progress(tickSeconds); dumpWriter.Wait(1); } } } }