public unsafe static void Save(Song song, string filename, int sampleRate, int loopCount, int duration, int channelMask, bool separateFiles, bool separateIntro, Action <short[], string> function) { var project = song.Project; var introDuration = separateIntro ? GetIntroDuration(song, sampleRate) : 0; if (separateFiles) { for (int channelIdx = 0; channelIdx < song.Channels.Length; channelIdx++) { var channelBit = 1 << channelIdx; if ((channelBit & channelMask) != 0) { var player = new WavPlayer(sampleRate, loopCount, channelBit); var samples = player.GetSongSamples(song, project.PalMode, duration); if (introDuration > 0) { var loopSamples = new short[samples.Length - introDuration]; Array.Copy(samples, introDuration, loopSamples, 0, loopSamples.Length); Array.Resize(ref samples, introDuration); var channelIntroFileName = Utils.AddFileSuffix(filename, "_" + song.Channels[channelIdx].ShortName + "_Intro"); var channelLoopFileName = Utils.AddFileSuffix(filename, "_" + song.Channels[channelIdx].ShortName); function(samples, channelIntroFileName); function(loopSamples, channelLoopFileName); } else { var channelFileName = Utils.AddFileSuffix(filename, "_" + song.Channels[channelIdx].ShortName); function(samples, channelFileName); } } } } else { var player = new WavPlayer(sampleRate, loopCount, channelMask); var samples = player.GetSongSamples(song, project.PalMode, duration); if (introDuration > 0) { var loopSamples = new short[samples.Length - introDuration]; Array.Copy(samples, introDuration, loopSamples, 0, loopSamples.Length); Array.Resize(ref samples, introDuration); var introFileName = Utils.AddFileSuffix(filename, "_Intro"); var loopFileName = filename; function(samples, introFileName); function(loopSamples, loopFileName); } else { function(samples, filename); } } }
private void ExportWavMp3() { var props = dialog.GetPropertyPage((int)ExportFormat.WavMp3); var format = props.GetPropertyValue <string>(1); var filename = ""; if (format == "MP3") { filename = lastExportFilename != null ? lastExportFilename : PlatformUtils.ShowSaveFileDialog("Export MP3 File", "MP3 Audio File (*.mp3)|*.mp3", ref Settings.LastExportFolder); } else { filename = lastExportFilename != null ? lastExportFilename : PlatformUtils.ShowSaveFileDialog("Export Wave File", "Wave Audio File (*.wav)|*.wav", ref Settings.LastExportFolder); } if (filename != null) { var songName = props.GetPropertyValue <string>(0); var sampleRate = Convert.ToInt32(props.GetPropertyValue <string>(2), CultureInfo.InvariantCulture); var bitRate = Convert.ToInt32(props.GetPropertyValue <string>(3), CultureInfo.InvariantCulture); var loopCount = props.GetPropertyValue <string>(4) != "Duration" ? props.GetPropertyValue <int>(5) : -1; var duration = props.GetPropertyValue <string>(4) == "Duration" ? props.GetPropertyValue <int>(6) : -1; var separateFiles = props.GetPropertyValue <bool>(7); var selectedChannels = props.GetPropertyValue <bool[]>(8); var song = project.GetSong(songName); if (separateFiles) { for (int i = 0; i < selectedChannels.Length; i++) { if (selectedChannels[i]) { var channelFilename = Utils.AddFileSuffix(filename, "_" + song.Channels[i].ShortName); if (format == "MP3") { Mp3File.Save(song, channelFilename, sampleRate, bitRate, loopCount, duration, 1 << i); } else { WaveFile.Save(song, channelFilename, sampleRate, loopCount, duration, 1 << i); } } } } else { var channelMask = 0; for (int i = 0; i < selectedChannels.Length; i++) { if (selectedChannels[i]) { channelMask |= (1 << i); } } if (format == "MP3") { Mp3File.Save(song, filename, sampleRate, bitRate, loopCount, duration, channelMask); } else { WaveFile.Save(song, filename, sampleRate, loopCount, duration, channelMask); } } lastExportFilename = filename; } }
private void WavMp3Export(string filename, bool mp3) { var extension = mp3 ? "mp3" : "wav"; if (!ValidateExtension(filename, "." + extension)) { return; } var songIndex = ParseOption("export-song", 0); var sampleRate = ParseOption($"{extension}-export-rate", 44100); var loopCount = ParseOption($"{extension}-export-loop", 1); var duration = ParseOption($"{extension}-export-duration", 0); var mask = ParseOption($"{extension}-export-channels", 0xff, true); var separate = HasOption($"{extension}-export-separate-channels"); var bitrate = ParseOption($"{extension}-export-bitrate", 192); var song = GetProjectSong(songIndex); if (duration > 0) { loopCount = -1; } else { loopCount = Math.Max(1, loopCount); } if (song != null) { if (separate) { for (int i = 0; i < song.Channels.Length; i++) { if ((mask & (1 << i)) != 0) { var channelFilename = Utils.AddFileSuffix(filename, "_" + song.Channels[i].ExportName); if (mp3) { Mp3File.Save(song, channelFilename, sampleRate, bitrate, loopCount, duration, 1 << i); } else { WaveFile.Save(song, channelFilename, sampleRate, loopCount, duration, 1 << i); } } } } else { if (mp3) { Mp3File.Save(song, filename, sampleRate, bitrate, loopCount, duration, mask); } else { WaveFile.Save(song, filename, sampleRate, loopCount, duration, mask); } } } }
public unsafe static void Save(Song song, string filename, int sampleRate, int loopCount, int duration, int channelMask, bool separateFiles, bool separateIntro, bool stereo, float[] pan, Action <short[], int, string> function) { var project = song.Project; var introDuration = separateIntro ? GetIntroDuration(song, sampleRate) : 0; if (channelMask == 0) { return; } if (separateFiles) { for (int channelIdx = 0; channelIdx < song.Channels.Length; channelIdx++) { var channelBit = 1 << channelIdx; if ((channelBit & channelMask) != 0) { var player = new WavPlayer(sampleRate, loopCount, channelBit, Settings.SeparateChannelsExportTndMode); var samples = player.GetSongSamples(song, project.PalMode, duration); if (introDuration > 0) { var loopSamples = new short[samples.Length - introDuration]; Array.Copy(samples, introDuration, loopSamples, 0, loopSamples.Length); Array.Resize(ref samples, introDuration); var channelIntroFileName = Utils.AddFileSuffix(filename, "_" + song.Channels[channelIdx].ShortName + "_Intro"); var channelLoopFileName = Utils.AddFileSuffix(filename, "_" + song.Channels[channelIdx].ShortName); function(samples, 1, channelIntroFileName); function(loopSamples, 1, channelLoopFileName); } else { var channelFileName = Utils.AddFileSuffix(filename, "_" + song.Channels[channelIdx].ShortName); function(samples, 1, channelFileName); } } } } else { var numChannels = 1; var samples = (short[])null; if (stereo) { // Get all the samples for all channels. var channelSamples = new short[song.Channels.Length][]; var numStereoSamples = 0; for (int channelIdx = 0; channelIdx < song.Channels.Length; channelIdx++) { var channelBit = 1 << channelIdx; if ((channelBit & channelMask) != 0) { var player = new WavPlayer(sampleRate, loopCount, channelBit, NesApu.TND_MODE_SEPARATE); channelSamples[channelIdx] = player.GetSongSamples(song, project.PalMode, duration); numStereoSamples = Math.Max(numStereoSamples, channelSamples[channelIdx].Length); } } // Mix and interleave samples. samples = new short[numStereoSamples * 2]; for (int i = 0; i < numStereoSamples; i++) { float l = 0; float r = 0; for (int j = 0; j < channelSamples.Length; j++) { if (channelSamples[j] != null) { float sl = 1.0f - Utils.Clamp(2.0f * (pan[j] - 0.5f), 0.0f, 1.0f); float sr = 1.0f - Utils.Clamp(-2.0f * (pan[j] - 0.5f), 0.0f, 1.0f); l += channelSamples[j][i] * sl; r += channelSamples[j][i] * sr; } } samples[i * 2 + 0] = (short)Utils.Clamp((int)Math.Round(l), short.MinValue, short.MaxValue); samples[i * 2 + 1] = (short)Utils.Clamp((int)Math.Round(r), short.MinValue, short.MaxValue); } numChannels = 2; introDuration *= 2; } else { var player = new WavPlayer(sampleRate, loopCount, channelMask); samples = player.GetSongSamples(song, project.PalMode, duration); } if (introDuration > 0) { var loopSamples = new short[samples.Length - introDuration]; Array.Copy(samples, introDuration, loopSamples, 0, loopSamples.Length); Array.Resize(ref samples, introDuration); var introFileName = Utils.AddFileSuffix(filename, "_Intro"); var loopFileName = filename; function(samples, numChannels, introFileName); function(loopSamples, numChannels, loopFileName); } else { function(samples, numChannels, filename); } } }