/// <summary> /// Sets the audio stream tempo to match another audio stream's tempo /// </summary> /// <param name="changeTrack">The audio stream to change the temp of.</param> /// <param name="matchTrack">The audio stream to match the BPM of</param> public static void SetTrackTempoToMatchAnotherTrack(Track changeTrack, Track matchTrack) { if (changeTrack == null || matchTrack == null) return; if (!changeTrack.IsAudioLoaded()) return; if (!matchTrack.IsAudioLoaded()) return; var percentChange = (float)(BpmHelper.GetAdjustedBpmPercentChange(changeTrack.EndBpm, matchTrack.StartBpm)); Bass.BASS_ChannelSetAttribute(changeTrack.Channel, BASSAttribute.BASS_ATTRIB_TEMPO, percentChange); }
/// <summary> /// Unloads the track audio data. /// </summary> /// <param name="track">The track.</param> public void UnloadTrackAudioData(Track track) { if (!track.IsAudioLoaded()) return; DebugHelper.WriteLine("Unloading track Audio Data " + track.Description); AudioStreamHelper.RemoveFromMixer(track, _trackMixer.ChannelId); AudioStreamHelper.UnloadAudio(track); track.SyncProc = null; }
/// <summary> /// Sets the audio stream pitch to match another audioStream's BPM /// </summary> /// <param name="changeTrack">The audio stream to change the pitch of.</param> /// <param name="matchTrack">The audio stream to match the BPM of</param> public static void SetTrackPitchToMatchAnotherTrack(Track changeTrack, Track matchTrack) { if (changeTrack == null || matchTrack == null) return; if (!changeTrack.IsAudioLoaded()) return; if (!matchTrack.IsAudioLoaded()) return; var sampleRate = GetTrackTempoChangeAsSampleRate(changeTrack, matchTrack); Bass.BASS_ChannelSetAttribute(changeTrack.Channel, BASSAttribute.BASS_ATTRIB_TEMPO_FREQ, sampleRate); }
/// <summary> /// Loads the track audio data. /// </summary> /// <param name="track">The track to load.</param> /// <returns> /// The loaded track /// </returns> public Track LoadTrackAudioData(Track track) { // abort if audio data already loaded if (track.IsAudioLoaded()) return track; // ensure mp3 tag data is loaded if (!track.TagDataLoaded) LoadTagData(track); DebugHelper.WriteLine("Loading track Audio Data " + track.Description); lock (track) { AudioStreamHelper.LoadAudio(track); track.FadeInStart = 0; track.FadeInStartVolume = (float) (DefaultFadeInStartVolume/100); track.FadeInEndVolume = (float) (DefaultFadeInEndVolume/100); track.FadeOutEnd = 0; track.FadeOutStartVolume = (float) (DefaultFadeOutStartVolume/100); track.FadeOutEndVolume = (float) (DefaultFadeOutEndVolume/100); ExtenedAttributesHelper.LoadExtendedAttributes(track); if (track.FadeOutStart == 0) { if (LimitSongLength && track.LengthSeconds > MaxSongLength) { track.FadeOutStart = track.SecondsToSamples(MaxSongLength - DefaultFadeLength - 1); } else { track.FadeOutStart = track.SecondsToSamples(track.LengthSeconds - DefaultFadeLength - 1); } } if (track.FadeInEnd == track.FadeInStart || track.FadeInEnd == 0) { track.FadeInEnd = track.FadeInStart + track.SecondsToSamples(BpmHelper.GetBestFitLoopLength(track.StartBpm, DefaultFadeLength)); } if (track.FadeOutEnd == track.FadeInStart || track.FadeOutEnd == 0) { track.FadeOutEnd = track.FadeOutStart + track.SecondsToSamples(BpmHelper.GetBestFitLoopLength(track.EndBpm, DefaultFadeLength)); } if (!track.UsePreFadeIn) { track.PreFadeInStart = track.FadeInStart; track.PreFadeInStartVolume = 0; } } AddToRecentTracks(track); DebugHelper.WriteLine("Finished loading track Audio Data " + track.Description); return track; }
/// <summary> /// Unloads the track stream data. /// </summary> /// <param name="track">The track to unload.</param> private void RemoveTrackFromMixer(Track track) { if (track == null) return; if (!track.IsAudioLoaded()) return; AudioStreamHelper.Pause(track); DebugHelper.WriteLine("Remove track from mixer " + track.Description); ClearTrackSyncPositions(track); UnloadTrackAudioData(track); track.SyncProc = null; }
/// <summary> /// Clears the track sync positions. /// </summary> /// <param name="track">The track.</param> private void ClearTrackSyncPositions(Track track) { DebugHelper.WriteLine("Clear track sync positions " + track.Description); if (track.IsAudioLoaded()) { if (track.FadeInStartSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.FadeInStartSyncId); track.FadeInStartSyncId = int.MinValue; } if (track.FadeInEndSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.FadeInEndSyncId); track.FadeInEndSyncId = int.MinValue; } if (track.FadeOutStartSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.FadeOutStartSyncId); track.FadeOutStartSyncId = int.MinValue; } if (track.FadeOutEndSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.FadeOutEndSyncId); track.FadeInStartSyncId = int.MinValue; } if (track.PreFadeInStartSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.PreFadeInStartSyncId); track.PreFadeInStartSyncId = int.MinValue; } if (track.TrackEndSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.TrackEndSyncId); track.TrackEndSyncId = int.MinValue; } if (track.RawLoopEndSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.RawLoopEndSyncId); track.TrackEndSyncId = int.MinValue; } if (track.ExtendedMixEndSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.ExtendedMixEndSyncId); track.ExtendedMixEndSyncId = int.MinValue; } if (track.SkipSyncId != int.MinValue) { BassMix.BASS_Mixer_ChannelRemoveSync(track.Channel, track.SkipSyncId); track.SkipSyncId = int.MinValue; } } ClearAutomationSyncPositions(track); }
/// <summary> /// Sets a track sync. /// </summary> /// <param name="track">The track.</param> /// <param name="position">The position.</param> /// <param name="syncType">Type of the sync.</param> /// <returns>The sync Id</returns> private static int SetTrackSync(Track track, long position, SyncType syncType) { if (!track.IsAudioLoaded()) throw new Exception("Track audio not loaded"); var flags = BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME; if (syncType == SyncType.TrackEnd) { flags = BASSSync.BASS_SYNC_END; position = 0; } lock (track) { var syncId = BassMix.BASS_Mixer_ChannelSetSync(track.Channel, flags, position, track.SyncProc, new IntPtr((int) syncType)); switch (syncType) { case SyncType.StartPreFadeIn: track.PreFadeInStartSyncId = syncId; break; case SyncType.StartFadeIn: track.FadeInStartSyncId = syncId; break; case SyncType.EndFadeIn: track.FadeInEndSyncId = syncId; break; case SyncType.StartFadeOut: track.FadeOutStartSyncId = syncId; break; case SyncType.EndFadeOut: track.FadeOutEndSyncId = syncId; break; case SyncType.TrackEnd: track.TrackEndSyncId = syncId; break; case SyncType.EndRawLoop: track.RawLoopEndSyncId = syncId; break; case SyncType.EndExtendedMix: track.ExtendedMixEndSyncId = syncId; break; case SyncType.StartTrackFxTrigger: break; case SyncType.EndTrackFxTrigger: break; case SyncType.StartSampleTrigger: break; case SyncType.EndSampleTrigger: break; case SyncType.StartSkipSection: break; default: throw new ArgumentOutOfRangeException(nameof(syncType), syncType, null); } return syncId; } }
/// <summary> /// Adds to the mixer channel, and sets the sync points. /// </summary> /// <param name="track">The track to sync.</param> private void AddTrackToMixer(Track track) { if (track == null) return; DebugHelper.WriteLine("Add track to mixer " + track.Description); WaitForLock(); Lock(); track.ResetPowerDownOnEnd(); // load audio data if not loaded if (!track.IsAudioLoaded()) { LoadTrackAudioData(track); } if (track != PreviousTrack && track != CurrentTrack) { lock (MixerLock) { // add the new track to the mixer (in paused mode) AudioStreamHelper.AddToMixer(track, _trackMixer.ChannelId); // set track sync event track.SyncProc = OnTrackSync; track.CurrentStartLoop = 0; track.CurrentEndLoop = 0; if (PreviousTrack == null) { AudioStreamHelper.SetPosition(track, 0); AudioStreamHelper.SetVolume(track, 1F); } else if (track.UsePreFadeIn) { AudioStreamHelper.SetPosition(track, track.PreFadeInStart); AudioStreamHelper.SetVolume(track, track.PreFadeInStartVolume); } else { AudioStreamHelper.SetPosition(track, track.FadeInStart); AudioStreamHelper.SetVolume(track, track.FadeInStartVolume); } } } Unlock(); }