private static extern void midi_WavFileOut( IntPtr filePath, IntPtr pWaveTable, INST_LIST *list, uint sampleRate, uint bitRate, IntPtr pEvents, uint eventSize, uint baseTick );
public Sender(string dlsPath) { uint fileSize = 0; mpWaveTable = waveout_LoadWaveTable(Marshal.StringToHGlobalAuto(dlsPath), out fileSize); mpInstList = (INST_LIST *)Marshal.AllocHGlobal(Marshal.SizeOf <INST_LIST>()); var dls = new DLS.DLS(mpWaveTable, fileSize); dls.GetInstList(mpInstList); //var sf2 = new SF2.SF2(dlsPath, mpWaveTable, fileSize); //sf2.GetInstList(mpInstList); waveout_SystemValues(SampleRate, 16, 220, 50, CHANNEL_COUNT, SAMPLER_COUNT); mppChannels = waveout_GetChannelPtr(); mppSamplers = waveout_GetSamplerPtr(); mppNotes = waveout_GetNotePtr(); midi_CreateChannels(mpInstList, mppSamplers, mppNotes, mppChannels, SAMPLER_COUNT); mppChParam = midi_GetChannelParamPtr(); waveout_Open(); }
unsafe public void GetInstList(INST_LIST *list) { list->instCount = 0; list->ppInst = (INST_REC **)Marshal.AllocHGlobal(sizeof(INST_REC *) * Instruments.List.Count); foreach (var inst in Instruments.List) { list->ppInst[list->instCount] = (INST_REC *)Marshal.AllocHGlobal(Marshal.SizeOf <INST_REC>()); var pInst = list->ppInst[list->instCount]; list->instCount++; // pInst->id.isDrum = (byte)(inst.Header.locale.bankFlags == 0x80 ? 1 : 0); pInst->id.programNo = inst.Header.locale.programNo; pInst->id.bankMSB = inst.Header.locale.bankMSB; pInst->id.bankLSB = inst.Header.locale.bankLSB; pInst->regionCount = inst.Regions.List.Count; if (string.IsNullOrWhiteSpace(inst.Name)) { pInst->pName = Marshal.StringToHGlobalAuto(string.Format( "MSB:{0} LSB:{1} PROG:{2}", pInst->id.bankMSB.ToString("000"), pInst->id.bankLSB.ToString("000"), pInst->id.programNo.ToString("000") )); } else { pInst->pName = Marshal.StringToHGlobalAuto(inst.Name); } if (string.IsNullOrWhiteSpace(inst.Category)) { if (0 < pInst->id.isDrum) { pInst->pCategory = Marshal.StringToHGlobalAuto("Drum set"); } else { pInst->pCategory = Marshal.StringToHGlobalAuto(""); } } else { pInst->pCategory = Marshal.StringToHGlobalAuto(inst.Category); } pInst->ppRegions = (REGION **)Marshal.AllocHGlobal(sizeof(REGION *) * inst.Regions.List.Count); #region instEnv var instEnv = new ENVELOPE(); instEnv.deltaA = 1000.0 * Sender.DeltaTime * Sender.AttackSpeed; // 1msec instEnv.deltaD = 1000.0 * Sender.DeltaTime * Sender.DecaySpeed; // 1msec instEnv.deltaR = 1000.0 * Sender.DeltaTime * Sender.ReleaseSpeed; // 1msec instEnv.levelS = 1.0; instEnv.hold = 0.0; if (null != inst.Articulations) { foreach (var conn in inst.Articulations.Art.List) { if (SRC_TYPE.NONE != conn.source) { continue; } switch (conn.destination) { case DST_TYPE.EG1_ATTACK_TIME: instEnv.deltaA = Sender.AttackSpeed * Sender.DeltaTime / ART.GetValue(conn); instEnv.hold += ART.GetValue(conn); break; case DST_TYPE.EG1_HOLD_TIME: instEnv.hold += ART.GetValue(conn); break; case DST_TYPE.EG1_DECAY_TIME: instEnv.deltaD = Sender.DecaySpeed * Sender.DeltaTime / ART.GetValue(conn); break; case DST_TYPE.EG1_RELEASE_TIME: instEnv.deltaR = Sender.ReleaseSpeed * Sender.DeltaTime / ART.GetValue(conn); break; case DST_TYPE.EG1_SUSTAIN_LEVEL: instEnv.levelS = (0.0 == ART.GetValue(conn)) ? 1.0 : (ART.GetValue(conn) * 0.01); break; } } } if (instEnv.hold < Sender.DeltaTime) { instEnv.hold = Sender.DeltaTime; } #endregion var ppRegions = pInst->ppRegions; var rgnIdx = 0; foreach (var rgn in inst.Regions.List) { ppRegions[rgnIdx] = (REGION *)Marshal.AllocHGlobal(Marshal.SizeOf <REGION>()); var pRegion = ppRegions[rgnIdx]; rgnIdx++; if (null == rgn.Articulations) { pRegion->env = instEnv; } else { #region regionEnv var regionEnv = new ENVELOPE(); regionEnv.deltaA = 1000.0 * Sender.DeltaTime * Sender.AttackSpeed; // 1msec regionEnv.deltaD = 1000.0 * Sender.DeltaTime * Sender.DecaySpeed; // 1msec regionEnv.deltaR = 1000.0 * Sender.DeltaTime * Sender.ReleaseSpeed; // 1msec regionEnv.levelS = 1.0; regionEnv.hold = 0.0; foreach (var conn in rgn.Articulations.Art.List) { if (SRC_TYPE.NONE != conn.source) { continue; } switch (conn.destination) { case DST_TYPE.EG1_ATTACK_TIME: regionEnv.deltaA = Sender.AttackSpeed * Sender.DeltaTime / ART.GetValue(conn); regionEnv.hold += ART.GetValue(conn); break; case DST_TYPE.EG1_HOLD_TIME: regionEnv.hold += ART.GetValue(conn); break; case DST_TYPE.EG1_DECAY_TIME: regionEnv.deltaD = Sender.DecaySpeed * Sender.DeltaTime / ART.GetValue(conn); break; case DST_TYPE.EG1_SUSTAIN_LEVEL: regionEnv.levelS = (0.0 == ART.GetValue(conn)) ? 1.0 : (ART.GetValue(conn) * 0.01); break; case DST_TYPE.EG1_RELEASE_TIME: regionEnv.deltaR = Sender.ReleaseSpeed * Sender.DeltaTime / ART.GetValue(conn); break; } } if (regionEnv.hold < Sender.DeltaTime) { regionEnv.hold = Sender.DeltaTime; } #endregion pRegion->env = regionEnv; } var wave = WavePool.List[(int)rgn.WaveLink.tableIndex]; var samples = wave.Size / wave.Format.blockAlign; pRegion->waveInfo.waveOfs = wave.Addr - (uint)mDlsPtr.ToInt64(); if (rgn.HasSampler) { pRegion->waveInfo.gain = rgn.Sampler.Gain / 32768.0; pRegion->waveInfo.unityNote = (byte)rgn.Sampler.unityNote; pRegion->waveInfo.delta = Math.Pow(2.0, rgn.Sampler.fineTune / 1200.0) * wave.Format.sampleRate / Sender.SampleRate; ; if (rgn.HasLoop) { pRegion->waveInfo.loopBegin = rgn.Loops[0].start; pRegion->waveInfo.loopLength = rgn.Loops[0].length; pRegion->waveInfo.loopEnable = true; } else if (wave.HasLoop) { pRegion->waveInfo.loopBegin = wave.Loops[0].start; pRegion->waveInfo.loopLength = wave.Loops[0].length; pRegion->waveInfo.loopEnable = true; } else { pRegion->waveInfo.loopBegin = 0; pRegion->waveInfo.loopLength = samples; pRegion->waveInfo.loopEnable = false; pRegion->env.deltaR = Sender.DeltaTime * pRegion->waveInfo.delta / samples; } } else { pRegion->waveInfo.gain = wave.Sampler.Gain / 32768.0; pRegion->waveInfo.unityNote = (byte)wave.Sampler.unityNote; pRegion->waveInfo.delta = Math.Pow(2.0, wave.Sampler.fineTune / 1200.0) * wave.Format.sampleRate / Sender.SampleRate; ; if (wave.HasLoop) { pRegion->waveInfo.loopBegin = wave.Loops[0].start; pRegion->waveInfo.loopLength = wave.Loops[0].length; pRegion->waveInfo.loopEnable = true; } else { pRegion->waveInfo.loopBegin = 0; pRegion->waveInfo.loopLength = samples; pRegion->waveInfo.loopEnable = false; } } pRegion->keyLo = (byte)rgn.Header.key.low; pRegion->keyHi = (byte)rgn.Header.key.high; pRegion->velLo = (byte)rgn.Header.velocity.low; pRegion->velHi = (byte)rgn.Header.velocity.high; } } }
unsafe public void GetInstList(INST_LIST *list) { list->instCount = 0; list->ppInst = (INST_REC **)Marshal.AllocHGlobal(sizeof(INST_REC *) * mPdta.PresetList.Count); foreach (var preset in mPdta.PresetList) { list->ppInst[list->instCount] = (INST_REC *)Marshal.AllocHGlobal(Marshal.SizeOf <INST_REC>()); var pInst = list->ppInst[list->instCount]; list->instCount++; // pInst->id.isDrum = (byte)(0 < preset.Key.isDrum ? 1 : 0); pInst->id.programNo = preset.Key.programNo; pInst->id.bankMSB = preset.Key.bankMSB; pInst->id.bankLSB = preset.Key.bankLSB; if (string.IsNullOrWhiteSpace(preset.Value.Item1)) { pInst->pName = Marshal.StringToHGlobalAuto(string.Format( "MSB:{0} LSB:{1} PROG:{2}", pInst->id.bankMSB.ToString("000"), pInst->id.bankLSB.ToString("000"), pInst->id.programNo.ToString("000") )); } else { pInst->pName = Marshal.StringToHGlobalAuto(preset.Value.Item1); } if (0 < pInst->id.isDrum) { pInst->pCategory = Marshal.StringToHGlobalAuto("Drum set"); } else { pInst->pCategory = Marshal.StringToHGlobalAuto(""); } // pInst->regionCount = 0; foreach (var pv in preset.Value.Item2) { foreach (var iv in mPdta.InstList[pv.instId].Item2) { pInst->regionCount++; } } pInst->ppRegions = (REGION **)Marshal.AllocHGlobal(sizeof(REGION *) * pInst->regionCount); // var ppRegions = pInst->ppRegions; var rgnIdx = 0; foreach (var pv in preset.Value.Item2) { foreach (var iv in mPdta.InstList[pv.instId].Item2) { ppRegions[rgnIdx] = (REGION *)Marshal.AllocHGlobal(Marshal.SizeOf <REGION>()); var pRegion = ppRegions[rgnIdx]; rgnIdx++; // pRegion->keyLo = Math.Max(pv.keyLo, iv.keyLo); pRegion->keyHi = Math.Min(pv.keyHi, iv.keyHi); pRegion->velLo = Math.Max(pv.velLo, iv.velLo); pRegion->velHi = Math.Min(pv.velHi, iv.velHi); // var smpl = mPdta.SHDR[iv.sampleId]; var waveBegin = smpl.start + iv.waveBegin; pRegion->waveInfo.waveOfs = (uint)(mSdta.pData.ToInt64() - mSf2Ptr.ToInt64() + waveBegin * 2); // pRegion->waveInfo.loopEnable = iv.loopEnable; if (pRegion->waveInfo.loopEnable) { pRegion->waveInfo.loopBegin = smpl.loopstart - waveBegin; pRegion->waveInfo.loopLength = smpl.loopend - smpl.loopstart; } else { var waveEnd = smpl.end + iv.waveEnd; pRegion->waveInfo.loopBegin = 0; pRegion->waveInfo.loopLength = waveEnd - waveBegin; } // if (0 <= iv.rootKey) { pRegion->waveInfo.unityNote = (byte)iv.rootKey; } else if (0 <= pv.rootKey) { pRegion->waveInfo.unityNote = (byte)pv.rootKey; } else { pRegion->waveInfo.unityNote = smpl.originalKey; } // pRegion->waveInfo.gain = pv.gain * iv.gain / 32768.0; pRegion->waveInfo.delta = iv.fineTune * iv.coarseTune * smpl.sampleRate / Sender.SampleRate; pRegion->env = iv.env; } } } }
private static extern void midi_CreateChannels(INST_LIST *list, IntPtr ppSmpl, NOTE **ppNote, IntPtr ppCh, int samplerCount);