NLayer MpegFile转换为SFML.净SoundStream

本文关键字:SoundStream SFML MpegFile 转换 NLayer | 更新日期: 2023-09-27 18:07:00

我目前正在研究SFML。Net扩展与mp3支持。因此,我写了一个Stream类,使用NLayer MpegFile来解码mp3。

public class Mp3StreamSFML : SoundStream
{
    private MpegFile mp3file;
    private int currentBufferSize;
    private short[] currentBuffer;
    public Mp3StreamSFML(String _filename)
    {
        mp3file = new MpegFile(_filename);
        Initialize((uint)mp3file.Channels, (uint)mp3file.SampleRate);
        currentBufferSize = 0;
        currentBuffer = new short[currentBufferSize];
    }
    #region implemented abstract members of SoundStream
    protected override bool OnGetData(out short[] samples)
    {
        if (currentBufferSize <= mp3file.Position)
        {
            byte[] buffer = new byte[512];
            if (mp3file.ReadSamples(buffer, 0, buffer.Length) > 0)
            {
                Array.Resize(ref currentBuffer, currentBuffer.Length + (buffer.Length / 2));
                Buffer.BlockCopy(buffer, 0, currentBuffer, currentBufferSize, buffer.Length);
                currentBufferSize = currentBuffer.Length;
            }
            samples = currentBuffer;
            return true;
        } 
        else
        {
            samples = currentBuffer;
            return false;
        }
    }
    protected override void OnSeek(TimeSpan timeOffset)
    {
        mp3file.Position = (long)timeOffset.TotalSeconds;
    }
    #endregion
}

我是这样用的:

                try
                {
                    stream = new Mp3StreamSFML(this.objProgram.getObjCuesheet().getAudiofilePath(true));
                    stream.Play();
                    log.debug("samplerate = " + stream.SampleRate);
                }
                catch(Exception ex)
                {
                    log.fatal(ex.ToString());
                }

不幸的是,没有正确的声音播放,它只是"抖动",听起来真的很奇怪。我做错了什么?似乎是两个框架之间的问题。

谢谢你的帮助。斯文

NLayer MpegFile转换为SFML.净SoundStream

是这样解决的:

using System;
using SFML.Audio;
using NLayer;
using System.Threading;
namespace AudioCuesheetEditor.AudioBackend.SFML
{
    /// <summary>
    /// Class for mp3 decoded audio files to use in SFML as Soundstream, since SFML doesn't support mp3 decoding (for legal reasons).
    /// </summary>
    public class Mp3StreamSFML : SoundStream
    {
        private static readonly Logfile log = Logfile.getLogfile(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private MpegFile mp3file;
        private Mutex mutex;
        /// <summary>
        /// Initializes a new instance of the <see cref="AudioCuesheetEditor.AudioBackend.SFML.Mp3StreamSFML"/> class.
        /// </summary>
        /// <param name="_filename">Full path to the file</param>
        public Mp3StreamSFML(String _filename)
        {
            log.debug("Constructor called with " + _filename);
            this.mp3file = new MpegFile(_filename);
            this.Initialize((uint)this.mp3file.Channels, (uint)this.mp3file.SampleRate);
            this.mutex = new Mutex();
        }
        public TimeSpan Duration
        {
            get
            {
                log.debug("Duration = " + this.mp3file.Duration);
                return this.mp3file.Duration;
            }
        }
        #region implemented abstract members of SoundStream
        protected override bool OnGetData(out short[] samples)
        {
            log.debug("OnGetData called");
            this.mutex.WaitOne();
            //Buffer data for about 1 second
            float[] normalizedaudiodata = new float[48000];
            int readSamples = this.mp3file.ReadSamples(normalizedaudiodata, 0, normalizedaudiodata.Length);
            short[] pcmaudiodata;
            if (readSamples > 0)
            {
                pcmaudiodata = new short[readSamples]; // converted data
                for (int i = 0; i < readSamples; i++)
                {
                    // clip the data
                    if (normalizedaudiodata[i] > 1.0f)
                    {
                        normalizedaudiodata[i] = 1.0f;
                    }
                    else
                    {
                        if (normalizedaudiodata[i] < -1.0f)
                        {
                            normalizedaudiodata[i] = -1.0f;
                        }
                    }
                    // convert to pcm data
                    pcmaudiodata[i] = (short)(normalizedaudiodata[i] * short.MaxValue);
                }
                samples = pcmaudiodata;
                this.mutex.ReleaseMutex();
                return true;
            }
            else
            {
                samples = null;
                this.mutex.ReleaseMutex();
                return false;
            }
        }
        protected override void OnSeek(TimeSpan timeOffset)
        {
            log.debug("OnSeek called with " + timeOffset);
            this.mutex.WaitOne();
            if ((timeOffset <= this.mp3file.Duration) && (timeOffset >= TimeSpan.Zero))
            {
                this.mp3file.Time = timeOffset;
            }
            this.mutex.ReleaseMutex();
        }
        #endregion
    }
}