コード例 #1
0
        private static unsafe void AllocateAndPrimeBuffers(AudioStream *pThis)
        {
            OSStatus status = API.AudioQueueAllocateBufferWithPacketDescriptions(pThis->Queue, pThis->BufferByteSize, pThis->NumPacketsToRead, &pThis->Buffer0);

            API.CheckStatus(status);

            status = API.AudioQueueAllocateBufferWithPacketDescriptions(pThis->Queue, pThis->BufferByteSize, pThis->NumPacketsToRead, &pThis->Buffer1);
            API.CheckStatus(status);

            status = API.AudioQueueAllocateBufferWithPacketDescriptions(pThis->Queue, pThis->BufferByteSize, pThis->NumPacketsToRead, &pThis->Buffer2);
            API.CheckStatus(status);

            pThis->IsRunning = true;

            if (pThis->Buffer0 == null)
            {
                Console.WriteLine("AudioQueueAllocateBufferWithPacketDescriptions failed to allocate buffer0 of size " + pThis->BufferByteSize);
            }

            if (pThis->Buffer1 == null)
            {
                Console.WriteLine("AudioQueueAllocateBufferWithPacketDescriptions failed to allocate buffer0 of size " + pThis->BufferByteSize);
            }

            if (pThis->Buffer2 == null)
            {
                Console.WriteLine("AudioQueueAllocateBufferWithPacketDescriptions failed to allocate buffer0 of size " + pThis->BufferByteSize);
            }

            ReadBufferProc(pThis, pThis->Queue, pThis->Buffer0);
            ReadBufferProc(pThis, pThis->Queue, pThis->Buffer1);
            ReadBufferProc(pThis, pThis->Queue, pThis->Buffer2);
        }
コード例 #2
0
        internal static void Play(AudioStream *pThis)
        {
            // start the queue
            OSStatus status = API.AudioQueueStart(pThis->Queue, null);

            API.CheckStatus(status);
        }
コード例 #3
0
        static unsafe void PropertyChangeInternal(void *pUserData, AudioQueue *pQueue, AudioQueueProperty id)
        {
            AudioStream *pThis = (AudioStream *)pUserData;

            if (pThis == null)
            {
                Console.WriteLine("PropertyChangeProc: pThis is null");
            }

            if (pQueue == null)
            {
                Console.WriteLine("PropertyChangeProc: pQueue is null");
            }

            int      size       = sizeof(uint);
            uint     iIsRunning = 0;
            OSStatus status     = API.AudioQueueGetProperty(pQueue, AudioQueueProperty.IsRunning, &iIsRunning, &size);

            API.CheckStatus(status);

            bool isRunning = iIsRunning != 0;

            if (status == 0)
            {
                if (pThis->IsRunning && !isRunning)
                {
                    AudioStream.Stop(pThis);
                }
            }
        }
コード例 #4
0
        public unsafe static AudioStream *AllocateStream()
        {
            AudioStream *pThis = (AudioStream *)Marshal.AllocHGlobal(sizeof(AudioStream));

            API.ZeroMemory(pThis, sizeof(AudioStream));

            return(pThis);
        }
コード例 #5
0
 private static unsafe void OpenFileAndCreateStream(AudioStream *pThis, string url)
 {
     using (NSUrl nsUrl = new NSUrl(url))
     {
         OSStatus status = API.AudioFileOpenURL(nsUrl.Handle, AudioFilePermissions.Read, 0, &pThis->AudioFile);
         API.CheckStatus(status);
     }
 }
コード例 #6
0
        public unsafe static void Create(AudioStream *pThis, string url)
        {
            OpenFileAndCreateStream(pThis, url);

            CreateQueue(pThis);

            CopyPropertyFromFileToQueue(pThis, AudioFileProperty.MagicCookieData, AudioQueueProperty.MagicCookie);
            CopyPropertyFromFileToQueue(pThis, AudioFileProperty.ChannelLayout, AudioQueueProperty.ChannelLayout);

            API.AudioQueueAddPropertyListener(pThis->Queue, AudioQueueProperty.IsRunning, OnPropertyChange, pThis);

            AllocateAndPrimeBuffers(pThis);
        }
コード例 #7
0
        internal static void Stop(AudioStream *pThis)
        {
            lock (API.StopLock)
            {
                OSStatus status = API.AudioQueueDispose(pThis->Queue, 1);
                API.CheckStatus(status);

                status = API.AudioFileClose(pThis->AudioFile);
                API.CheckStatus(status);

                Marshal.FreeHGlobal((IntPtr)pThis);

                Sound.OnDisposeStream(pThis);
            }
        }
コード例 #8
0
        private static unsafe void CopyPropertyFromFileToQueue(AudioStream *pThis, AudioFileProperty fileProp, AudioQueueProperty queueProp)
        {
            int      size   = sizeof(uint);
            OSStatus status = API.AudioFileGetPropertyInfo(pThis->AudioFile, fileProp, &size, null);

            if (status == 0 && size > 0)
            {
                void *pData = (void *)Marshal.AllocHGlobal(size);

                API.AudioFileGetProperty(pThis->AudioFile, fileProp, &size, pData);
                API.AudioQueueSetProperty(pThis->Queue, queueProp, pData, size);

                Marshal.FreeHGlobal((IntPtr)pData);
            }
        }
コード例 #9
0
        internal static void OnDisposeStream(AudioStream *pStream)
        {
            lock (Sound.Map)
            {
                Sound sound  = null;
                bool  exists = Sound.Map.TryGetValue((IntPtr)pStream, out sound);

                if (exists)
                {
                    Sound.Map.Remove((IntPtr)pStream);

                    if (sound != null)
                    {
                        sound.Stream = null;
                    }
                }
            }
        }
コード例 #10
0
        private static unsafe void CreateQueue(AudioStream *pThis)
        {
            int dataFormatSize = sizeof(AudioStreamBasicDescription);
            AudioStreamBasicDescription *pDataFormat = &pThis->DataFormat;

            OSStatus status = API.AudioFileGetProperty(pThis->AudioFile, AudioFileProperty.DataFormat, &dataFormatSize, pDataFormat);

            API.CheckStatus(status);

            status = API.AudioQueueNewOutput(pDataFormat, OnReadBuffer, pThis, null, null, 0, &pThis->Queue);
            API.CheckStatus(status);

            dataFormatSize = sizeof(int);
            int *pMaxPacketSize = &pThis->MaxPacketSize;

            status = API.AudioFileGetProperty(pThis->AudioFile, AudioFileProperty.PacketSizeUpperBound, &dataFormatSize, pMaxPacketSize);
            API.CheckStatus(status);

            DeriveBufferSize(&pThis->DataFormat, pThis->MaxPacketSize, 0.5, &pThis->BufferByteSize, &pThis->NumPacketsToRead);
        }
コード例 #11
0
 private Sound(AudioStream *stream)
 {
     this.Stream = stream;
 }
コード例 #12
0
        internal static unsafe void SetVolume(AudioStream *pThis, float volume)
        {
            OSStatus status = API.AudioQueueSetParameter(pThis->Queue, AudioQueueParameter.Volume, volume);

            API.CheckStatus(status);
        }
コード例 #13
0
        static unsafe void ReadBufferInternal(void *pUserData, AudioQueue *pQueue, AudioQueueBuffer *pBuffer)
        {
            AudioStream *pThis = (AudioStream *)pUserData;

            if (pThis == null)
            {
                Console.WriteLine("ReadBufferProc: pThis is null");
            }

            if (!pThis->IsRunning)
            {
                return;
            }

            if (pQueue == null)
            {
                Console.WriteLine("ReadBufferProc: pQueue is null");
            }

            if (pBuffer == null)
            {
                Console.WriteLine("ReadBufferProc: pBuffer is null");
            }

            if (pBuffer->AudioData == null)
            {
                Console.WriteLine("ReadBufferProc: pBuffer->AudioData is null");
            }

            if (pBuffer->PacketDescriptors == null)
            {
                Console.WriteLine("ReadBufferProc: pBuffer->PacketDescriptors is null");
            }

            if (pThis->AudioFile == null)
            {
                Console.WriteLine("ReadBufferProc: pThis->AudioFile is null");
            }

            int numPacketsReadFromFile = pThis->NumPacketsToRead;
            int numBytesReadFromFile   = 0;

            OSStatus status = API.AudioFileReadPackets(pThis->AudioFile, 0, &numBytesReadFromFile, pBuffer->PacketDescriptors, pThis->CurrentPacket, &numPacketsReadFromFile, pBuffer->AudioData);

            API.CheckStatus(status);

            if (status == 0 &&
                numPacketsReadFromFile == 0 &&
                pThis->Looping)
            {
                // we ran out of packets and they are
                // asking to loop, so try and reset
                pThis->CurrentPacket   = 0;
                numPacketsReadFromFile = pThis->NumPacketsToRead;
                numBytesReadFromFile   = 0;
                status = API.AudioFileReadPackets(pThis->AudioFile, 0, &numBytesReadFromFile, pBuffer->PacketDescriptors, pThis->CurrentPacket, &numPacketsReadFromFile, pBuffer->AudioData);
                API.CheckStatus(status);
            }

            if (numPacketsReadFromFile > 0)
            {
                pBuffer->AudioDataByteSize     = numBytesReadFromFile;
                pBuffer->PacketDescriptorCount = numPacketsReadFromFile;

                status = API.AudioQueueEnqueueBuffer(pThis->Queue, pBuffer, (pBuffer->PacketDescriptors != null ? pBuffer->PacketDescriptorCount : 0), pBuffer->PacketDescriptors);
                API.CheckStatus(status);

                pThis->CurrentPacket += numPacketsReadFromFile;
            }
            else
            {
                status = API.AudioQueueStop(pThis->Queue, 0);
                API.CheckStatus(status);
            }
        }