public override SongContent Process(AudioContent input, ContentProcessorContext context) { // Fallback if we aren't buiding for iOS. var platform = ContentHelper.GetMonoGamePlatform(); if (platform != MonoGamePlatform.iOS && platform != MonoGamePlatform.Linux) return base.Process(input, context); //TODO: If quality isn't best and it's a .wma, don't compress to MP3. Leave it as a .wav instead string outputType = (platform == MonoGamePlatform.iOS) ? "mp3" : "wav"; string outputFilename = Path.ChangeExtension(context.OutputFilename, outputType); string directoryName = Path.GetDirectoryName(outputFilename); if (!Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); var inputFilename = Path.GetFullPath(input.FileName); // XNA's songprocessor converts the bitrate on the input file based // on it's conversion quality. //http://blogs.msdn.com/b/etayrien/archive/2008/09/22/audio-input-and-output-formats.aspx int desiredOutputBitRate = 0; switch (this.Quality) { case ConversionQuality.Low: desiredOutputBitRate = 96000; break; case ConversionQuality.Medium: desiredOutputBitRate = 128000; break; case ConversionQuality.Best: desiredOutputBitRate = 192000; break; } AudioFileType target = (platform == MonoGamePlatform.iOS) ? AudioFileType.Mp3 : AudioFileType.Wav; // Create a new file if we need to. FileStream outputStream = input.FileType != target ? new FileStream(outputFilename, FileMode.Create) : null; if (input.FileType != target) AudioConverter.ConvertFile(inputFilename, outputStream, target, desiredOutputBitRate, input.Format.BitsPerSample, input.Format.ChannelCount); else File.Copy(inputFilename, outputFilename, true); if (outputStream != null) outputStream.Close(); context.AddOutputFile(outputFilename); // SoundEffectContent is a sealed class, construct it using reflection var type = typeof(SongContent); ConstructorInfo c = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(int) }, null); var outputSongContent = (SongContent)c.Invoke(new Object[] { Path.GetFileName(outputFilename), (int)input.Duration.TotalMilliseconds }); return outputSongContent; }
public void Compile() { ParsedPath wavFileName = Target.InputFiles.Where(f => f.Extension == ".wav").First(); ParsedPath xnbFileName = Target.OutputFiles.Where(f => f.Extension == ".xnb").First(); WavFile wavFile = WavFileReader.ReadFile(wavFileName); AudioContent ac = new AudioContent(wavFile); if (!Directory.Exists(xnbFileName.VolumeAndDirectory)) Directory.CreateDirectory(xnbFileName.VolumeAndDirectory); XnbFileWriterV5.WriteFile(ac, xnbFileName); }
public static void WritePcmFile(AudioContent content, string saveToFile) { string ffmpegStdout, ffmpegStderr; var ffmpegExitCode = ExternalTool.Run( "ffmpeg", string.Format( "-y -i \"{0}\" -vn -c:a pcm_s16le -b:a 192000 -f:a wav -strict experimental \"{1}\"", content.FileName, saveToFile), out ffmpegStdout, out ffmpegStderr); if (ffmpegExitCode != 0) { throw new InvalidOperationException("ffmpeg exited with non-zero exit code: \n" + ffmpegStdout + "\n" + ffmpegStderr); } }
public override SoundEffectContent Process(AudioContent input, ContentProcessorContext context) { // Fallback if we aren't buiding for iOS. var platform = ContentHelper.GetMonoGamePlatform(); if (platform != MonoGamePlatform.iOS) return base.Process(input, context); var targetSampleRate = input.Format.SampleRate; // XNA SoundEffects have their sample rate changed based on the quality setting on the processor. //http://blogs.msdn.com/b/etayrien/archive/2008/09/22/audio-input-and-output-formats.aspx switch(this.Quality) { case ConversionQuality.Best: break; case ConversionQuality.Medium: targetSampleRate = (int)(targetSampleRate * 0.75f); break; case ConversionQuality.Low: targetSampleRate = (int)(targetSampleRate * 0.5f); break; } targetSampleRate = Math.Max(8000, targetSampleRate); var wavStream = new MemoryStream(); WaveFormat outputFormat = AudioConverter.ConvertFile(input.FileName, wavStream, AudioFileType.Wav, targetSampleRate, input.Format.BitsPerSample, input.Format.ChannelCount); var outputData = new ReadOnlyCollection<byte>(wavStream.ToArray()); wavStream.Close(); var waveFormatHeader = writeWavHeader(outputFormat); // SoundEffectContent is a sealed class, construct it using reflection var type = typeof(SoundEffectContent); ConstructorInfo c = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(ReadOnlyCollection<byte>), typeof(ReadOnlyCollection<byte>), typeof(int), typeof(int), typeof(int) }, null); var outputSoundEffectContent = (SoundEffectContent)c.Invoke(new Object[] { waveFormatHeader, outputData, input.LoopStart, input.LoopLength, (int)input.Duration.TotalMilliseconds }); return outputSoundEffectContent; }
public override ConversionQuality ConvertStreamingAudio(TargetPlatform platform, ConversionQuality quality, AudioContent content, ref string outputFileName) { // Most platforms will use AAC ("mp4") by default var targetFormat = ConversionFormat.Aac; if (platform == TargetPlatform.Windows || platform == TargetPlatform.WindowsPhone8 || platform == TargetPlatform.WindowsStoreApp) { targetFormat = ConversionFormat.WindowsMedia; } else if (platform == TargetPlatform.DesktopGL) { targetFormat = ConversionFormat.Vorbis; } // Get the song output path with the target format extension. outputFileName = Path.ChangeExtension(outputFileName, AudioHelper.GetExtension(targetFormat)); // Make sure the output folder for the file exists. Directory.CreateDirectory(Path.GetDirectoryName(outputFileName)); return(ConvertToFormat(content, targetFormat, quality, outputFileName)); }
public static ConversionQuality ConvertToFormat(AudioContent content, ConversionFormat formatType, ConversionQuality quality, string saveToFile) { var temporaryOutput = Path.GetTempFileName(); try { string ffmpegCodecName, ffmpegMuxerName; //int format; switch (formatType) { case ConversionFormat.Adpcm: // ADPCM Microsoft ffmpegCodecName = "adpcm_ms"; ffmpegMuxerName = "wav"; //format = 0x0002; /* WAVE_FORMAT_ADPCM */ break; case ConversionFormat.Pcm: // XNA seems to preserve the bit size of the input // format when converting to PCM. if (content.Format.BitsPerSample == 8) { ffmpegCodecName = "pcm_u8"; } else if (content.Format.BitsPerSample == 32 && content.Format.Format == 3) { ffmpegCodecName = "pcm_f32le"; } else { ffmpegCodecName = "pcm_s16le"; } ffmpegMuxerName = "wav"; //format = 0x0001; /* WAVE_FORMAT_PCM */ break; case ConversionFormat.WindowsMedia: // Windows Media Audio 2 ffmpegCodecName = "wmav2"; ffmpegMuxerName = "asf"; //format = 0x0161; /* WAVE_FORMAT_WMAUDIO2 */ break; case ConversionFormat.Xma: throw new NotSupportedException( "XMA is not a supported encoding format. It is specific to the Xbox 360."); case ConversionFormat.ImaAdpcm: // ADPCM IMA WAV ffmpegCodecName = "adpcm_ima_wav"; ffmpegMuxerName = "wav"; //format = 0x0011; /* WAVE_FORMAT_IMA_ADPCM */ break; case ConversionFormat.Aac: // AAC (Advanced Audio Coding) // Requires -strict experimental ffmpegCodecName = "aac"; ffmpegMuxerName = "ipod"; //format = 0x0000; /* WAVE_FORMAT_UNKNOWN */ break; case ConversionFormat.Vorbis: // Vorbis ffmpegCodecName = "libvorbis"; ffmpegMuxerName = "ogg"; //format = 0x0000; /* WAVE_FORMAT_UNKNOWN */ break; default: // Unknown format throw new NotSupportedException(); } string ffmpegStdout, ffmpegStderr; int ffmpegExitCode; do { ffmpegExitCode = ExternalTool.Run( "ffmpeg", string.Format( "-y -i \"{0}\" -vn -c:a {1} -b:a {2} -ar {3} -f:a {4} -strict experimental \"{5}\"", content.FileName, ffmpegCodecName, QualityToBitRate(quality), QualityToSampleRate(quality, content.Format.SampleRate), ffmpegMuxerName, temporaryOutput), out ffmpegStdout, out ffmpegStderr); if (ffmpegExitCode != 0) { quality--; } } while (quality >= 0 && ffmpegExitCode != 0); if (ffmpegExitCode != 0) { throw new InvalidOperationException("ffmpeg exited with non-zero exit code: \n" + ffmpegStdout + "\n" + ffmpegStderr); } byte[] rawData; using (var fs = new FileStream(temporaryOutput, FileMode.Open, FileAccess.Read)) { rawData = new byte[fs.Length]; fs.Read(rawData, 0, rawData.Length); } if (saveToFile != null) { using (var fs = new FileStream(saveToFile, FileMode.Create, FileAccess.Write)) fs.Write(rawData, 0, rawData.Length); } // Use probe to get the final format and information on the converted file. AudioFileType audioFileType; AudioFormat audioFormat; TimeSpan duration; int loopStart, loopLength; ProbeFormat(temporaryOutput, out audioFileType, out audioFormat, out duration, out loopStart, out loopLength); AudioFormat riffAudioFormat; byte[] data = StripRiffWaveHeader(rawData, out riffAudioFormat); // deal with adpcm if (audioFormat.Format == 2 || audioFormat.Format == 17) { // riff contains correct blockAlign audioFormat = riffAudioFormat; // fix loopLength -> has to be multiple of sample per block // see https://msdn.microsoft.com/de-de/library/windows/desktop/ee415711(v=vs.85).aspx int samplesPerBlock = SampleAlignment(audioFormat); loopLength = (int)(audioFormat.SampleRate * duration.TotalSeconds); int remainder = loopLength % samplesPerBlock; loopLength += samplesPerBlock - remainder; } content.SetData(data, audioFormat, duration, loopStart, loopLength); } finally { ExternalTool.DeleteFile(temporaryOutput); } return(quality); }
public override ConversionQuality ConvertAudio(TargetPlatform platform, ConversionQuality quality, AudioContent content) { // Default to PCM data, or ADPCM if the source is ADPCM. var targetFormat = ConversionFormat.Pcm; if (quality != ConversionQuality.Best || content.Format.Format == 2 || content.Format.Format == 17) { if (platform == TargetPlatform.iOS || platform == TargetPlatform.MacOSX || platform == TargetPlatform.DesktopGL) { targetFormat = ConversionFormat.ImaAdpcm; } else { targetFormat = ConversionFormat.Adpcm; } } return(ConvertToFormat(content, targetFormat, quality, null)); }
public override ConversionQuality ConvertAudio(TargetPlatform platform, ConversionQuality quality, AudioContent content) { // Default to PCM data. var targetFormat = ConversionFormat.Pcm; if (quality != ConversionQuality.Best) { if (platform == TargetPlatform.iOS || platform == TargetPlatform.MacOSX) { targetFormat = ConversionFormat.ImaAdpcm; } else { targetFormat = ConversionFormat.Adpcm; } } return(ConvertToFormat(content, targetFormat, quality, null)); }
/// <summary> /// Converts the audio content to a streaming format that works on targeted platform. /// </summary> /// <param name="platform">The platform to build the audio content for.</param> /// <param name="quality">The suggested audio quality level.</param> /// <param name="content">he audio content to convert.</param> /// <param name="outputFileName"></param> /// <returns>The quality used for conversion which could be different from the suggested quality.</returns> public abstract ConversionQuality ConvertStreamingAudio(TargetPlatform platform, ConversionQuality quality, AudioContent content, ref string outputFileName);
/// <summary> /// Converts the audio content to work on targeted platform. /// </summary> /// <param name="platform">The platform to build the audio content for.</param> /// <param name="quality">The suggested audio quality level.</param> /// <param name="content">The audio content to convert.</param> /// <returns>The quality used for conversion which could be different from the suggested quality.</returns> public abstract ConversionQuality ConvertAudio(TargetPlatform platform, ConversionQuality quality, AudioContent content);