public M4AWrappedSample(int offset) { this.offset = offset; if (offset == 0 || !ROM.IsValidRomOffset(offset)) { goto fail; } sample = ROM.Instance.Reader.ReadObject <M4AMLSSSample>(offset); if (!ROM.IsValidRomOffset(sample.Length + (offset + 0x10))) { goto fail; } gSample = new WrappedSample(sample.DoesLoop == 0x40000000, sample.LoopPoint, sample.Length, sample.Frequency >> 10, false); gSample.SetOffset(offset + 0x10); return; fail: sample = new M4AMLSSSample(); gSample = null; Console.WriteLine("Error loading instrument at 0x{0:X}.", offset); }
public void Init(byte ownerIdx, Note note, ADSR adsr, WrappedSample sample, byte vol, sbyte pan, int pitch, bool bFixed) { State = ADSRState.Initializing; pos = 0; processStep = 0; interPos = 0; OwnerIdx = ownerIdx; Note = note; this.adsr = adsr; this.sample = sample; this.bFixed = bFixed; bGoldenSun = (ROM.Instance.Game.Engine.HasGoldenSunSynths && sample.bLoop && sample.LoopPoint == 0 && sample.Length == 0); if (bGoldenSun) { gsPSG = ROM.Instance.Reader.ReadObject <GoldenSunPSG>(sample.GetOffset()); } SetVolume(vol, pan); SetPitch(pitch); }
public MLSSWrappedSample(int offset) { sample = ROM.Instance.Reader.ReadObject <M4AMLSSSample>(offset); gSample = new WrappedSample(sample.DoesLoop == 0x40000000, sample.LoopPoint, sample.Length, sample.Frequency >> 10, true); SetOffset(offset); }
public DirectSoundChannel NewDSNote(byte owner, ADSR env, Note note, byte vol, sbyte pan, int pitch, bool bFixed, WrappedSample sample, Track[] tracks) { DirectSoundChannel nChn = null; var byOwner = dsChannels.OrderByDescending(c => c.OwnerIdx); foreach (var i in byOwner) // Find free { if (i.State == ADSRState.Dead || i.OwnerIdx == 0xFF) { nChn = i; break; } } if (nChn == null) // Find releasing { foreach (var i in byOwner) { if (i.State == ADSRState.Releasing) { nChn = i; break; } } } if (nChn == null) // Find prioritized { foreach (var i in byOwner) { if (owner >= 16 || tracks[owner].Priority > tracks[i.OwnerIdx].Priority) { nChn = i; break; } } } if (nChn == null) // None available { var lowest = byOwner.First(); // Kill lowest track's instrument if the track is lower than this one if (lowest.OwnerIdx >= owner) { nChn = lowest; } } if (nChn != null) // Could still be null from the above if { nChn.Init(owner, note, env, sample, vol, pan, pitch, bFixed); } return(nChn); }
public Channel PlayNote(Track track, sbyte note, byte velocity, int duration) { int shift = note + track.KeyShift; note = (sbyte)(shift.Clamp(0, 0x7F)); track.PrevNote = note; if (!track.Ready) { return(null); } var owner = track.Index; WrappedVoice voice = null; bool fromDrum = false; try { voice = Song.VoiceTable.GetVoiceFromNote(track.Voice, note, out fromDrum); } catch { System.Console.WriteLine("Track {0} tried to play a bad note... Voice {1} Note {2}", owner, track.Voice, note); return(null); } var aNote = new Note { Duration = duration, Velocity = velocity, OriginalKey = note, Key = fromDrum ? voice.Voice.GetRootNote() : note }; if (voice.Voice is M4AVoiceEntry m4a) { M4AVoiceType type = (M4AVoiceType)(m4a.Type & 0x7); switch (type) { case M4AVoiceType.Direct: bool bFixed = (m4a.Type & (int)M4AVoiceFlags.Fixed) == (int)M4AVoiceFlags.Fixed; return(SoundMixer.Instance.NewDSNote(owner, m4a.ADSR, aNote, track.GetVolume(), track.GetPan(), track.GetPitch(), bFixed, ((M4AWrappedDirect)voice).Sample.GetSample(), tracks)); case M4AVoiceType.Square1: case M4AVoiceType.Square2: return(SoundMixer.Instance.NewGBNote(owner, m4a.ADSR, aNote, track.GetVolume(), track.GetPan(), track.GetPitch(), type, m4a.SquarePattern)); case M4AVoiceType.Wave: return(SoundMixer.Instance.NewGBNote(owner, m4a.ADSR, aNote, track.GetVolume(), track.GetPan(), track.GetPitch(), type, m4a.Address - ROM.Pak)); case M4AVoiceType.Noise: return(SoundMixer.Instance.NewGBNote(owner, m4a.ADSR, aNote, track.GetVolume(), track.GetPan(), track.GetPitch(), type, m4a.NoisePattern)); } } else if (voice.Voice is MLSSVoice mlssvoice) { MLSSVoiceEntry entry; bool bFixed = false; WrappedSample sample = null; try { entry = mlssvoice.GetEntryFromNote(note); bFixed = entry.IsFixedFrequency == 0x80; sample = ((MLSSVoiceTable)Song.VoiceTable).Samples[entry.Sample].GetSample(); } catch { System.Console.WriteLine("Track {0} tried to play a bad note... Voice {1} Note {2}", owner, track.Voice, note); return(null); } if (sample != null) { return(SoundMixer.Instance.NewDSNote(owner, new ADSR { A = 0xFF, S = 0xFF }, aNote, track.GetVolume(), track.GetPan(), track.GetPitch(), bFixed, sample, tracks)); } } return(null); }