Encapsulates and provides operations, such as format conversions, on the source audio. This type is produced by the audio importers and used by audio processors to produce compiled audio assets.
Inheritance: ContentItem, IDisposable
Exemplo n.º 1
0
        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);
            }
        }
Exemplo n.º 4
0
        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;
        }
Exemplo n.º 5
0
        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));
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
0
        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));
        }
Exemplo n.º 9
0
 /// <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);
Exemplo n.º 10
0
 /// <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);