Example #1
0
        public override void BufferData(int index, AudioChunk chunk)
        {
            if (chunk.Length > dataSizes[index])
            {
                IntPtr ptr = dataHandles[index];
                if (ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptr);
                }
                dataHandles[index] = Marshal.AllocHGlobal(chunk.Length);
            }

            IntPtr handle = dataHandles[index];

            fixed(byte *data = chunk.Data)
            {
                MemUtils.memcpy((IntPtr)data, handle, chunk.Length);
                ApplyVolume(handle, chunk);
            }

            WaveHeader header = default(WaveHeader);

            header.DataBuffer   = handle;
            header.BufferLength = chunk.Length;
            header.Loops        = 1;

            WaveHeader *hdr = (WaveHeader *)headers + index;

            *hdr = header;

            uint result = WinMM.waveOutPrepareHeader(devHandle, (IntPtr)hdr, waveHeaderSize);

            CheckError(result, "PrepareHeader");
            result = WinMM.waveOutWrite(devHandle, (IntPtr)hdr, waveHeaderSize);
            CheckError(result, "Write");
        }
        void SendNextBuffer( AudioChunk chunk )
        {
            Console.WriteLine( "send buffer " + buffersIndex );
            WaveHeader header = new WaveHeader();
            byte[] data = chunk.Data;
            GCHandle bufferHandle = GCHandle.Alloc( data, GCHandleType.Pinned );
            header.DataBuffer = bufferHandle.AddrOfPinnedObject();
            header.BufferLength = data.Length;
            header.Loops = 1;

            UserData userData = new UserData();
            userData.BufferHandle = bufferHandle;
            userData.Index = buffersIndex;
            GCHandle userDataHandle = GCHandle.Alloc( userData, GCHandleType.Pinned );
            header.UserData = GCHandle.ToIntPtr( userDataHandle );
            buffers[buffersIndex] = header;

            uint result = PrepareHeader( handle, ref buffers[buffersIndex], (uint)waveHeaderSize );
            CheckError( result );
            result = Write( handle, ref buffers[buffersIndex], (uint)waveHeaderSize );
            CheckError( result );
        }
 void ProcessWaveOutCallback( IntPtr handle, WaveOutMessage message, UIntPtr user, ref WaveHeader header, UIntPtr reserved )
 {
     Console.WriteLine( "callback:" + message + "," + buffersIndex );
     if( message == WaveOutMessage.Done ) {
         Free( ref header );
         // TODO: This probably needs to be rewritten.
         // Due to the asynchronous nature of WinMm, this function can be invoked on the thread that plays the music (I think?)
         // It would be much better regardless of this was invoked on the thread that called the player to begin with.
         if( chunks.MoveNext() ) {
             SendNextBuffer( chunks.Current );
             buffersIndex++;
         } else {
             if( buffersIndex <= 0 ) {
                 reachedEnd = true;
             }
         }
     }
 }
 void Free( ref WaveHeader header )
 {
     uint result = UnprepareHeader( handle, ref header, (uint)waveHeaderSize );
     CheckError( result );
     GCHandle userDataHandle = GCHandle.FromIntPtr( header.UserData );
     UserData userData = (UserData)userDataHandle.Target;
     GCHandle bufferHandle = userData.BufferHandle;
     bufferHandle.Free();
     buffersIndex = userData.Index;
 }
 static extern uint Write( IntPtr handle, ref WaveHeader header, uint headerByteSize );
 static extern uint UnprepareHeader( IntPtr handle, ref WaveHeader header, uint headerByteSize );