Ejemplo n.º 1
0
        public AudioEngine(string audioDevice = null, AudioDriver driver = AudioDriver.Default, int sampleRate = 44100, int bufferLength = 1024, ResampleQuality resampleQuality = ResampleQuality.High)
        {
            this.resampleQuality = resampleQuality;

            SDL.SDL_InitSubSystem(SDL.SDL_INIT_AUDIO);

            audioCallback = AudioCallback;
            SDL.SDL_AudioSpec desired = new SDL.SDL_AudioSpec()
            {
                freq     = sampleRate,
                format   = SDL.AUDIO_S16,
                channels = 2,
                samples  = (ushort)bufferLength,
                callback = audioCallback,
            };

            if (driver == AudioDriver.File)
            {
                audioSpec   = desired;
                audioDriver = driver;
            }
            else
            {
                string[] audioDrivers = new string[SDL.SDL_GetNumAudioDrivers()];
                for (int i = 0; i < audioDrivers.Length; i++)
                {
                    audioDrivers[i] = SDL.SDL_GetAudioDriver(i);
                }

                string driverName         = audioDrivers[0];
                string driverFallbackName = audioDrivers.Length > 1 ? audioDrivers[1] : null;

                if (driver != AudioDriver.Default)
                {
                    driverName = driver.ToString();
                }

                int init = SDL.SDL_AudioInit(driverName.ToLower());
                if (init != 0 && driverName == AudioDriver.XAudio2.ToString().ToLower() && driverFallbackName != null)
                {
                    // supplied SDL.dll does not support XAudio2, fallback to next driver
                    driverName = driverFallbackName;
                    init       = SDL.SDL_AudioInit(driverName.ToLower());
                }
                if (init != 0)
                {
                    throw new ApplicationException("Failed to initialize audio driver " + driverName + ": " + SDL.SDL_GetError());
                }

                Enum.TryParse(driverName, true, out audioDriver);

                if (audioDevice == null)
                {
                    string[] audioDevices = new string[SDL.SDL_GetNumAudioDevices(0)];
                    for (int i = 0; i < audioDevices.Length; i++)
                    {
                        audioDevices[i] = SDL.SDL_GetAudioDeviceName(i, 0);
                    }

                    audioDevice = audioDevices.Length > 0 ? audioDevices[0] : null;
                }

                outputDevice = SDL.SDL_OpenAudioDevice(audioDevice, 0, ref desired, out audioSpec, 0);
                if (outputDevice == 0)
                {
                    throw new ApplicationException("Failed to open audio device " + audioDevice + ": " + SDL.SDL_GetError());
                }
            }

            if (audioSpec.format == SDL.AUDIO_S32)
            {
                bytesPerSample = (uint)audioSpec.channels * 4;
            }
            else if (audioSpec.format == SDL.AUDIO_S16 || audioSpec.format == SDL.AUDIO_F32)
            {
                bytesPerSample = (uint)audioSpec.channels * 2;
            }
            else if (audioSpec.format == SDL.AUDIO_S8 || audioSpec.format == SDL.AUDIO_U8)
            {
                bytesPerSample = (uint)audioSpec.channels * 1;
            }

            if (audioSpec.size == 0)
            {
                audioSpec.size = audioSpec.samples * bytesPerSample;
            }

            emptyBuffer = new byte[audioSpec.size];
            audioBuffer = new byte[audioSpec.size];

            lastCallback = 0.0;
            bufferTimer  = Stopwatch.StartNew();

            if (outputDevice != 0)
            {
                SDL.SDL_PauseAudioDevice(outputDevice, 0);
            }
        }
Ejemplo n.º 2
0
        public static byte[] SoundFromFileResample(string path, int sampleRate, int channels, ushort sampleFormatSDL, ResampleQuality resampleQuality = ResampleQuality.High)
        {
            AVSampleFormat targetFormat2;

            switch (sampleFormatSDL)
            {
            case SDL.AUDIO_S16:
                targetFormat2 = AVSampleFormat.AV_SAMPLE_FMT_S16;
                break;

            case SDL.AUDIO_F32:
                targetFormat2 = AVSampleFormat.AV_SAMPLE_FMT_FLT;
                break;

            case SDL.AUDIO_S32:
                targetFormat2 = AVSampleFormat.AV_SAMPLE_FMT_S32;
                break;

            default:
                throw new ApplicationException("Could not map SDL audio format to AVSampleFormat: " + sampleFormatSDL.ToString());
            }

            using (FFmpegContext ffContext = FFmpegContext.Read(path))
            {
                ffContext.SelectStream(AVMediaType.AVMEDIA_TYPE_AUDIO);

                // setup resamplers and other format converters if needed
                ffContext.ConvertToFormat(targetFormat2, sampleRate, channels, resampleQuality);

                // FFmpeg only approximates stream durations but is
                // usually not far from the real duration.
                byte[] bytes = new byte[ffContext.audioBytesTotal];

                // read all data from frames
                long offset = 0;
                while (ffContext.ReadFrame())
                {
                    long frameSize = ffContext.GetFrameBufferSize();
                    if (offset + frameSize > bytes.Length)
                    {
                        Array.Resize(ref bytes, (int)(offset + frameSize));
                    }

                    offset += ffContext.GetFrameData(ref bytes, (int)offset);
                }

                return(bytes);
            }
        }
Ejemplo n.º 3
0
        public void ConvertToFormat(AVSampleFormat sampleFormat, int sampleRate, int channels, ResampleQuality resampleQuality = ResampleQuality.High)
        {
            if (format == (int)sampleFormat &&
                this.sampleRate == sampleRate &&
                this.channels == channels)
            {
                return;
            }

            format          = (int)sampleFormat;
            this.sampleRate = sampleRate;
            this.channels   = channels;

            int channelLayout = (int)ffmpeg.av_get_default_channel_layout(channels);

            swrContext = ffmpeg.swr_alloc();

            ffmpeg.av_opt_set_int(swrContext, "in_channel_layout", (int)codecContext->channel_layout, 0);
            ffmpeg.av_opt_set_int(swrContext, "out_channel_layout", channelLayout, 0);
            ffmpeg.av_opt_set_int(swrContext, "in_channel_count", codecContext->channels, 0);
            ffmpeg.av_opt_set_int(swrContext, "out_channel_count", channels, 0);
            ffmpeg.av_opt_set_int(swrContext, "in_sample_rate", codecContext->sample_rate, 0);
            ffmpeg.av_opt_set_int(swrContext, "out_sample_rate", sampleRate, 0);
            ffmpeg.av_opt_set_sample_fmt(swrContext, "in_sample_fmt", codecContext->sample_fmt, 0);
            ffmpeg.av_opt_set_sample_fmt(swrContext, "out_sample_fmt", sampleFormat, 0);

            switch (resampleQuality)
            {
            case ResampleQuality.Low:
                ffmpeg.av_opt_set_int(swrContext, "filter_size", 0, 0);
                ffmpeg.av_opt_set_int(swrContext, "phase_shift", 0, 0);
                break;

            case ResampleQuality.Medium:
                // default ffmpeg settings
                break;

            case ResampleQuality.High:
                ffmpeg.av_opt_set_int(swrContext, "filter_size", 128, 0);
                ffmpeg.av_opt_set_double(swrContext, "cutoff", 1.0, 0);
                break;

            case ResampleQuality.Highest:
                ffmpeg.av_opt_set_int(swrContext, "filter_size", 256, 0);
                ffmpeg.av_opt_set_double(swrContext, "cutoff", 1.0, 0);
                break;
            }

            if (ffmpeg.swr_init(swrContext) != 0)
            {
                throw new ApplicationException("Failed init SwrContext: " + FFmpegHelper.logLastLine);
            }
        }