/// <summary>
        /// Looks up the records for the given id
        /// </summary>
        /// <param name="id">The id of the file, event, etc</param>
        /// <returns>null if no information, otherwise, the record</returns>
        object InfoFor(uint id)
        {
            // First, map the id to a string, if possible
            object objId;
            var    name = AudioAssets.StringForID(id);

            if (null != name)
            {
                objId = name.ToUpper();
            }
            else
            {
                objId = id;
            }

            // Try looking up the record
            objectId2Info.TryGetValue(objId, out var ret);
            return(ret);
        }
        /// <summary>
        /// Add information about an id
        /// </summary>
        /// <param name="id">The internal 32-bit id form for events, sounds, etc.</param>
        /// <param name="info">Arbitrary extra information associated with the </param>
        void Add(uint id, object info)
        {
            // First, map the id to a string, if possible
            object objId;
            var    name = AudioAssets.StringForID(id);

            if (null != name)
            {
                objId = name.ToUpper();
            }
            else
            {
                objId = id;
            }
            // First, check that there is not already an ojbect in there with this
            // information
            if (objectId2Info.TryGetValue(objId, out _))
            {
                throw new System.Exception("dang, there should not be two.");
            }
            objectId2Info[objId] = info;
        }
        /// <summary>
        /// This reads a event to event action mapping
        /// </summary>
        /// <param name="eventId">the ID of the event that maps to an action</param>
        void ReadHIRCEvent(uint eventId, long endPos)
        {
            // Create a record so that we can look it up later
            var eventActions = new List <uint>();

            // Fetch each of event actions
            var numObjects = binaryReader.ReadUInt32();

            for (var idx = 0; idx < numObjects; idx++)
            {
                // Sanity check, since there is some weirdness with some files
                if (binaryReader.BaseStream.Position + 4 > endPos)
                {
                    break;
                }

                // Append the event action id to the list
                // Note: I don't know how this action id is created, it doesn't seem
                // to be in the various metadata text fieles
                eventActions.Add(binaryReader.ReadUInt32());
            }

            // Look up the record
            var info = (EventInfo)InfoFor(eventId);

            if (null != info)
            {
                info.EventActions = eventActions;
            }
            else
            {
                // map the id to this info
                var eventName = AudioAssets.StringForID(eventId);
                Add(eventId, new EventInfo {
                    SoundBankName = soundBankName, Name = eventName ?? (object)eventId, EventActions = eventActions
                });
            }
        }
        /// <summary>
        /// This reads a event to event action mapping
        /// </summary>
        /// <param name="eventId">the ID of the event that maps to an action</param>
        /// <remarks>
        /// The action Ids refer to objects created in the Event Action
        /// </remarks>
        void ReadHIRCEvent(uint eventId, long endPos)
        {
            // Create a record so that we can look it up later
            var eventActions = new List <uint>();

            // Fetch each of event actions
            // Note: this is a byte, not a uint32 as reported elsewhere
            var numObjects = binaryReader.ReadByte();

            for (var idx = 0; idx < numObjects; idx++)
            {
                // Sanity check, since there is some weirdness with some files
                if (binaryReader.BaseStream.Position + 4 > endPos)
                {
                    break;
                }

                // Append the event action id to the list
                eventActions.Add(binaryReader.ReadUInt32());
            }

            // Look up the record
            var info = (EventInfo)InfoFor(eventId);

            if (null != info)
            {
                info.EventActionIds = eventActions;
            }
            else
            {
                // map the id to this info
                var eventName = AudioAssets.StringForID(eventId);
                Add(eventId, new EventInfo {
                    SoundBank = this, Name = eventName ?? (object)eventId, EventActionIds = eventActions
                });
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public int Read(byte[] buffer, int offset, int count)
        {
            WaveBuffer waveBuffer = new WaveBuffer(buffer);
            var        outIdx     = 0;
            var        outBuf     = waveBuffer.ShortBuffer;

            if (null == reader)
            {
                return(0);
            }
            while (true)
            {
                // Do we need to replenish the bufer?
                if (null == samples)
                {
                    index = 0;
                    // Check that we haven't reached the end of the stream
                    // Todo: find a better way to capture the end of the line
                    if (reader.BaseStream.Position >= end)
                    {
                        reader.Dispose();
                        reader = null;
                        return(0);
                    }
                    // For each of the channels decode the samples and multiplex them in
                    var numChannels = WaveFormat.Channels;

                    // Get the decode sample buffer for the 1st channel
                    AudioAssets.Decode_wwise_ima(reader, chSamples);

                    if (1 == numChannels)
                    {
                        samples = chSamples;
                    }
                    else
                    {
                        // place it per the channels
                        var L = chSamples.Length;
                        for (var sampIdx = 0; sampIdx < L; sampIdx++)
                        {
                            dest[sampIdx * numChannels] = chSamples[sampIdx];
                        }

                        for (var ch = 1; ch < numChannels; ch++)
                        {
                            // Check that we haven't reached the end of the stream
                            // Todo: find a better way to capture the end of the line
                            if (reader.BaseStream.Position >= end)
                            {
                                reader.Dispose();
                                reader = null;
                                return(0);
                            }

                            // Get the decode sample buffer
                            AudioAssets.Decode_wwise_ima(reader, chSamples);
                            for (var sampIdx = 0; sampIdx < L; sampIdx++)
                            {
                                dest[sampIdx * numChannels + 1] = chSamples[sampIdx];
                            }
                        }
                        samples = dest;
                    }
                }

                // Copy the samples out
                var len = samples.Length;
                for (; count > 0 && index < len; index++, count -= 2)
                {
                    outBuf[outIdx++] = samples[index];
                }
                // Have we consumed the whole buffer?
                if (index >= samples.Length)
                {
                    samples = null;
                }
                // Are we done?
                if (count < 2)
                {
                    return(outIdx * 2);
                }
            }
        }