Example #1
0
        // ========================================================================================================================================
        #region Start / Stop

        void StartFMODSound(int sampleRate)
        {
            this.StopFMODSound();

            FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO();
            // exinfo.cbsize = sizeof(FMOD.CREATESOUNDEXINFO);
            exinfo.numchannels       = this.unityOAFRChannels;                                                              /* Number of channels in the sound. */
            exinfo.defaultfrequency  = sampleRate;                                                                          /* Default playback rate of sound. */
            exinfo.decodebuffersize  = (uint)this.unityOAFRDataLength;                                                      /* Chunk size of stream update in samples. This will be the amount of data passed to the user callback. */
            exinfo.length            = (uint)(exinfo.defaultfrequency * exinfo.numchannels * this.elementSize);             /* Length of PCM data in bytes of whole song (for Sound::getLength) */
            exinfo.format            = FMOD.SOUND_FORMAT.PCM16;                                                             /* Data format of sound. */
            exinfo.pcmreadcallback   = this.pcmreadcallback;                                                                /* User callback for reading. */
            exinfo.pcmsetposcallback = this.pcmsetposcallback;                                                              /* User callback for seeking. */

            result = system.createSound(""
                                        , FMOD.MODE.OPENUSER
                                        | FMOD.MODE.CREATESTREAM
                                        | FMOD.MODE.LOOP_NORMAL
                                        , ref exinfo
                                        , out sound);
            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, null, "system.createSound");

            AudioStreamSupport.LOG(LogLevel.DEBUG, this.logLevel, this.gameObjectName, null, "About to play...");

            result = system.playSound(sound, null, false, out channel);
            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, null, "system.playSound");
        }
Example #2
0
        FMOD.RESULT PCMReadCallback(System.IntPtr soundraw, System.IntPtr data, uint datalen)
        {
            // lock on pcmReadCallbackBuffer - can be changed ( added to ) in OAFR - here e.g. the underlying array can be changed while performing ToArray() leading to
            // 'Destination array was not long enough. Check destIndex and length, and the array's lower bounds'
            lock (this.pcmReadCallbackBufferLock)
            {
                var count = this.pcmReadCallbackBuffer[this.pcmReadCallback_ActiveBuffer].Count;

                AudioStreamSupport.LOG(LogLevel.DEBUG, this.logLevel, this.gameObjectName, null, "PCMReadCallback requested {0} while having {1}, time: {2}", datalen, count, AudioSettings.dspTime);

                if (count > 0 && count > datalen && datalen > 0)
                {
                    var bArr = this.pcmReadCallbackBuffer[this.pcmReadCallback_ActiveBuffer].ToArray();

                    System.Runtime.InteropServices.Marshal.Copy(bArr, 0, data, (int)datalen);

                    this.pcmReadCallbackBuffer[1 - this.pcmReadCallback_ActiveBuffer].AddRange(this.pcmReadCallbackBuffer[this.pcmReadCallback_ActiveBuffer].GetRange((int)datalen, count - (int)datalen));

                    this.pcmReadCallbackBuffer[this.pcmReadCallback_ActiveBuffer].Clear();

                    this.pcmReadCallback_ActiveBuffer = 1 - this.pcmReadCallback_ActiveBuffer;
                }
            }

            return(FMOD.RESULT.OK);
        }
Example #3
0
        void OnAudioFilterRead(float[] data, int channels)
        {
            if (data.Length != this.unityOAFRDataLength || channels != this.unityOAFRChannels)
            {
                this.unityOAFRDataLength = data.Length;
                this.unityOAFRChannels   = channels;

                AudioStreamSupport.LOG(LogLevel.DEBUG, this.logLevel, this.gameObjectName, null, "OAFR START {0} {1} {2}", this.unityOAFRDataLength, this.unityOAFRChannels, AudioSettings.dspTime);

                this.oafrDataFormatChanged = true;
            }

            if (channel != null)
            {
                var arr = this.FloatArrayToByteArray(data);
                // lock for PCMReadCallback
                lock (this.pcmReadCallbackBufferLock)
                {
                    this.pcmReadCallbackBuffer[this.pcmReadCallback_ActiveBuffer].AddRange(arr);
                }

                // the data have just been passed to fmod for processing - clear unity buffer - this component should be the last one in audio chain, i.e. at the bottom in the inspector
                Array.Clear(data, 0, data.Length);
            }
        }
Example #4
0
        // ========================================================================================================================================
        #region user support
        public void SetOutput(int _outputDriverID)
        {
            AudioStreamSupport.LOG(LogLevel.INFO, this.logLevel, this.gameObjectName, null, "Setting output to driver {0} ", _outputDriverID);

            result = system.setDriver(_outputDriverID);
            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, null, "system.setDriver");

            this.outputDriverID = _outputDriverID;
        }
Example #5
0
        // ========================================================================================================================================
        #region Unity lifecycle
        void Start()
        {
            this.gameObjectName = this.gameObject.name;


            result = FMOD.Factory.System_Create(out system);
            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, null, "FMOD.Factory.System_Create");

            result = system.getVersion(out version);
            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, null, "system.getVersion");

            if (version < FMOD.VERSION.number)
            {
                var msg = string.Format("FMOD lib version {0} doesn't match header version {1}", version, FMOD.VERSION.number);
                throw new System.Exception(msg);
            }

            int rate;

            FMOD.SPEAKERMODE sm;
            int sc;

            result = system.getSoftwareFormat(out rate, out sm, out sc);
            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, null, "system.getSoftwareFormat");

            AudioStreamSupport.LOG(LogLevel.INFO, this.logLevel, this.gameObjectName, null, "FMOD samplerate: {0}, speaker mode: {1}, num. of raw speakers {2}", rate, sm, sc);

            // TODO: evaluate maxchannels
            result = system.init(32, FMOD.INITFLAGS.NORMAL, extradriverdata);
            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, null, "system.init");


            this.SetOutput(this.outputDriverID);

            /* tags ERR_FILE_COULDNOTSEEK:
             *      http://stackoverflow.com/questions/7154223/streaming-mp3-from-internet-with-fmod
             *      http://www.fmod.org/docs/content/generated/FMOD_System_SetFileSystem.html
             */
            // result = system.setFileSystem(null, null, null, null, null, null, -1);
            // ERRCHECK(result, "system.setFileSystem");

            // Explicitly create the delegate object and assign it to a member so it doesn't get freed
            // by the garbage collected while it's being used
            this.pcmreadcallback   = new FMOD.SOUND_PCMREADCALLBACK(PCMReadCallback);
            this.pcmsetposcallback = new FMOD.SOUND_PCMSETPOSCALLBACK(PCMSetPosCallback);


            this.elementSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(System.Int16));


            // decodebuffersize samples worth of bytes will be called in read callback
            // createSound calls back, too
            this.pcmReadCallbackBuffer = new List <List <byte> >();
            this.pcmReadCallbackBuffer.Add(new List <byte>());
            this.pcmReadCallbackBuffer.Add(new List <byte>());
        }
Example #6
0
        float[] oafrDataArr = null; // instance buffer
        void OnAudioFilterRead(float[] data, int channels)
        {
            if (result == FMOD.RESULT.OK && openstate == FMOD.OPENSTATE.READY && this.isPlaying && !this.isPaused && !this.finished)
            {
                if (this.streamDataBytes == null || this.streamDataBytes.Length != (data.Length * 2))
                {
                    LOG(LogLevel.DEBUG, "Alocating new stream buffer of size {0}", data.Length * 2);

                    this.streamDataBytes = new byte[data.Length * 2];

                    this.streamDataBytesPinned.Free();
                    this.streamDataBytesPinned = GCHandle.Alloc(this.streamDataBytes, GCHandleType.Pinned);

                    this.streamDataBytesPtr = this.streamDataBytesPinned.AddrOfPinnedObject();
                }

                uint read = 2;
                result = this.sound.readData(this.streamDataBytesPtr, (uint)this.streamDataBytes.Length, out read);

                // ERRCHECK(result, "OAFR sound.readData", false);

                if (result == FMOD.RESULT.OK)
                {
                    if (read > 0)
                    {
                        int length = AudioStreamSupport.ByteArrayToFloatArray(this.streamDataBytes, read, ref this.oafrDataArr);
                        for (int i = 0; i < length; ++i)
                        {
                            data[i] += this.oafrDataArr[i];
                        }
                    }
                    else
                    {
                        /*
                         * do not attempt to read from empty buffer again
                         */
                        this.finished = true;
                    }
                }
                else
                {
                    /*
                     * do not attempt to read from buffer with error again
                     */
                    this.finished = true;
                }
            }
        }
Example #7
0
        float[] oafrDataArr = null; // instance buffer
        float[] GetAudioOutputBuffer(uint _len)
        {
            lock (this.outputBufferLock)
            {
                // 2 bytes per 1 value - adjust requested length
                uint len = _len * 2;

                if (len > outputBuffer.Count)
                {
                    return(null);
                }

                byte[] bArr = outputBuffer.GetRange(0, (int)len).ToArray();
                outputBuffer.RemoveRange(0, (int)len);

                AudioStreamSupport.ByteArrayToFloatArray(bArr, (uint)bArr.Length, ref oafrDataArr);

                return(this.oafrDataArr);
            }
        }
Example #8
0
 FMOD.RESULT PCMSetPosCallback(System.IntPtr soundraw, int subsound, uint position, FMOD.TIMEUNIT postype)
 {
     AudioStreamSupport.LOG(LogLevel.DEBUG, this.logLevel, this.gameObjectName, null, "PCMSetPosCallback requesting position {0} ", position);
     return(FMOD.RESULT.OK);
 }
Example #9
0
 protected void LOG(LogLevel requestedLogLevel, string format, params object[] args)
 {
     AudioStreamSupport.LOG(requestedLogLevel, this.logLevel, this.gameObjectName, this.OnError, format, args);
 }
Example #10
0
        // ========================================================================================================================================
        #region Support

        protected void ERRCHECK(FMOD.RESULT result, string customMessage, bool throwOnError = true)
        {
            this.lastError = result;

            AudioStreamSupport.ERRCHECK(result, this.logLevel, this.gameObjectName, this.OnError, customMessage, throwOnError);
        }