简体   繁体   中英

NLayer MpegFile to SFML.Net SoundStream

I'm currently working on SFML.Net to expand with mp3 support. Therefore I wrote a Stream class which uses NLayer MpegFile to decode the 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
}

I use it this way:

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

Unfortunately, there is not the correct sound played, its just "juttering" and sound really weird. What I'm doing wrong? Seems like a problem between the 2 Frameworks.

Thanks for your help. Sven

Solved the problem this way:

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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM