Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: NLayer MpegFile to SFML.Net SoundStream  (Read 14376 times)

0 Members and 1 Guest are viewing this topic.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #15 on: July 07, 2014, 01:30:36 pm »
Why are you reading a byte array when the library provides an overload that uses floats?
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #16 on: July 07, 2014, 01:47:56 pm »
Quote
if (currentBufferSize <= mp3file.Position)
What's the purpose of this test? I don't think you need it at all.

Quote
Array.Resize(ref currentBuffer, currentBuffer.Length + pcmaudiodata.Length);
OnGetData only expects a new chunk of fresh data. You mustn't return all the samples read in the previous calls, those have already been processed.
Laurent Gomila - SFML developer

s.baus

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #17 on: July 07, 2014, 04:02:07 pm »
Hello, thanks for your help. I now optimized the code to the following:

protected override bool OnGetData(out short[] samples)
        {
            float[] normalizedaudiodata = new float[128];
            int readSamples = mp3file.ReadSamples(normalizedaudiodata, 0, normalizedaudiodata.Length);
            short[] pcmaudiodata;
            if (readSamples > 0)
            {
                pcmaudiodata = new short[normalizedaudiodata.Length]; // converted data
                for (int i = 0; i < normalizedaudiodata.Length; 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;
                return true;
            }
            else
            {
                samples = null;
                return false;
            }
        }

But this also just doesn't work, I hear nothing :(. What can I do now?
AudioCuesheetEditor, your #1 CuesheetEditor.

http://sourceforge.net/projects/audiocuesheet

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #18 on: July 07, 2014, 04:19:10 pm »
new short[normalizedaudiodata.Length]

You need to use the actual number of samples that were read, not just the maximum length of your buffer.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

s.baus

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #19 on: July 08, 2014, 08:11:38 am »
new short[normalizedaudiodata.Length]

You need to use the actual number of samples that were read, not just the maximum length of your buffer.

Thanks for your help, I modified the code this way:

protected override bool OnGetData(out short[] samples)
        {
            float[] normalizedaudiodata = new float[128];
            int readSamples = 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;
                return true;
            }
            else
            {
                samples = null;
                return false;
            }
        }

I'm hearing nothing, Windows Sound sees my application wants to start audio output (I'm using windows 7) but there is no peak and nothing to hear. What I'm doing wrong?
AudioCuesheetEditor, your #1 CuesheetEditor.

http://sourceforge.net/projects/audiocuesheet

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #20 on: July 08, 2014, 08:25:05 am »
Can you show the other functions of your class?
Laurent Gomila - SFML developer

s.baus

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #21 on: July 08, 2014, 09:09:45 am »
Can you show the other functions of your class?
No Problem, here is the whole class ;):

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)
        {
            float[] normalizedaudiodata = new float[128];
            int readSamples = 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;
                return true;
            }
            else
            {
                samples = null;
                return false;
            }
        }

        protected override void OnSeek(TimeSpan timeOffset)
        {
            //TODO
            //mp3file.Position = 0;
            //mp3file.Position = (long)timeOffset.TotalSeconds;
        }

        #endregion
    }
AudioCuesheetEditor, your #1 CuesheetEditor.

http://sourceforge.net/projects/audiocuesheet

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #22 on: July 08, 2014, 09:31:55 am »
Ok, you haven't forgotten to call Initialize ;)

You should check (with the debugger or the console) the important values involved, to make sure everything is ok:
- mp3file.Channels
- mp3file.SampleRate
- readSamples everytime OnGetData is called
- if possible, a complete chunk of samples (in the middle of the music, to avoid silences that may occur at the beginning and end) to make sure the values are not weird

By the way, what is the "0" argument of ReadSamples? And shouldn't the array be passed with the "out" or "ref" keyword, if it is modified inside the function?
« Last Edit: July 08, 2014, 09:34:35 am by Laurent »
Laurent Gomila - SFML developer

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #23 on: July 08, 2014, 01:17:55 pm »
Try writing to the console the values of each sample before and after conversion and let us see the output.

Quote
what is the "0" argument of ReadSamples?

Probably the offset at which to write the samples into the buffer.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

s.baus

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #24 on: July 09, 2014, 07:43:12 am »
I tried a bit around, and you know what works? Setting the buffer size to 2048 (just a bit trying):

protected override bool OnGetData(out short[] samples)
        {
            float[] normalizedaudiodata = new float[2048];
            int readSamples = 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;
                return true;
            }
            else
            {
                samples = null;
                return false;
            }
        }

But I remember having read, that a too large buffer could decrease performance and therefore should be as little as possible. Do you have an idea, why it works with large buffer?
AudioCuesheetEditor, your #1 CuesheetEditor.

http://sourceforge.net/projects/audiocuesheet

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #25 on: July 09, 2014, 07:52:13 am »
In fact a small buffer is unlikely to work. I should have noticed before, 128 is indeed too small. At 44100 Hz, it's only 3 milliseconds of sound, which may not be enough to cover the time needed to decode another chunk in parallel. In other words, the sound stream spends all its time decoding small chunks. You're supposed to feed it with large chunks so that the audio driver is busy enough while you decode the next one (the Music class uses 1 second buffers).
Laurent Gomila - SFML developer

s.baus

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #26 on: July 09, 2014, 09:11:03 am »
No Problem, you helped me really much ;). How can calculate the sound buffer size to have 1 second of data?
AudioCuesheetEditor, your #1 CuesheetEditor.

http://sourceforge.net/projects/audiocuesheet

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: NLayer MpegFile to SFML.Net SoundStream
« Reply #27 on: July 09, 2014, 09:25:04 am »
How can calculate the sound buffer size to have 1 second of data?
Wolfram Alpha

But in this case, it's trivial: there are 44100 samples per second.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: