Author Topic: BASS_StreamCreateFileUser questions  (Read 684 times)

aybe

  • Posts: 145
BASS_StreamCreateFileUser questions
« on: 27 Sep '11 - 00:08 »
My audio source is an MP3 as a resource, it is returned as an array of bytes and this is how I implemented it.

- Is this properly implemented ?
- Can you tell why on creation, it seeks numerous times to the end of the file ?

Otherwise than that it works fine !

Thanks  :D

Code: [Select]
    public partial class Form1 : Form
    {
        private readonly byte[] _bytes = Resources.ZZZZZ;
        private readonly BASS_FILEPROCS _procs;
        private readonly PROGRESSPROC _progressproc;
        private long _index;

        public Form1()
        {
            InitializeComponent();
            _progressproc = Progressproc;
            _index = 0;
            _procs = new BASS_FILEPROCS(closeCallback, LengthCallback, ReadCallback, SeekCallback);
        }

        private void Form1Load(object sender, EventArgs e)
        {
            var handle = Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_NOBUFFER,
                                                        BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_STREAM_PRESCAN |
                                                        BASSFlag.BASS_SAMPLE_FLOAT, _procs, IntPtr.Zero);

                // I do call BASS_ChannelGetData in a loop
                // ...
        }

        private bool SeekCallback(long offset, IntPtr user)
        {
            _index = offset;
            return true;
        }

        private int ReadCallback(IntPtr buffer, int length, IntPtr user)
        {
            var copyIndex = (int) _index;
            var copyLength = length;

            if (copyIndex + copyLength > _bytes.Length)
            {
                // Fix last chunk length

                copyLength = _bytes.Length - copyIndex;
            }

            Marshal.Copy(_bytes, copyIndex, buffer, copyLength);
            _index += copyLength;

            return copyLength;
        }

        private long LengthCallback(IntPtr user)
        {
            return _bytes.Length;
        }

        private void closeCallback(IntPtr user)
        {
        }

    }

radio42

  • Posts: 4576
Re: BASS_StreamCreateFileUser questions
« Reply #1 on: 27 Sep '11 - 08:10 »
Looks fine as far as I can tell!
It seeks to the end of the file because of the following:
a) the BASS_STREAM_PRESCAN flag was used, as such the 'file' is fully scaned to determine the exact length
b) as TAGs might be located at the end of the file it needs to look for them

aybe

  • Posts: 145
Re: BASS_StreamCreateFileUser questions
« Reply #2 on: 27 Sep '11 - 15:58 »
Okay great, thanks a lot  :D

Ian @ un4seen

  • Administrator
  • Posts: 20433
Re: BASS_StreamCreateFileUser questions
« Reply #3 on: 27 Sep '11 - 16:05 »
My audio source is an MP3 as a resource, it is returned as an array of bytes and this is how I implemented it.

- Is this properly implemented ?
...

That looks fine, but a simpler (and more efficient) way to do it would be to pass the resource's memory block to BASS_StreamCreateFile :)

aybe

  • Posts: 145
Re: BASS_StreamCreateFileUser questions
« Reply #4 on: 27 Sep '11 - 20:27 »
Yes, right, I have just done it now  :D

Code: [Select]
  _gcHandle = GCHandle.Alloc(_bytes, GCHandleType.Pinned);
            IntPtr memory = _gcHandle.AddrOfPinnedObject();
            handle = Bass.BASS_StreamCreateFile(memory, 0, _bytes.Length,
                                       BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_STREAM_PRESCAN |
                                       BASSFlag.BASS_SAMPLE_FLOAT);

And of course, free the pinned object when finished ...

Thanks !