Example #1
0
        public static void PlaySample(Level level, WadSample sample, int channel, float volume = 1.0f, float pitch = 1.0f, float pan = 0.0f, int loopCount = 1)
        {
            if (volume <= 0.0f || loopCount <= 0)
            {
                return;
            }

            var disposables = new List <IDisposable>();

            try
            {
                // Load data.
                // If waveform data is loaded into memory, use it to play sound, otherwise find wav file on disk.

                WaveFileReader waveStream;
                MemoryStream   memoryStream;

                if (sample.IsLoaded)
                {
                    memoryStream = disposables.AddAndReturn(new MemoryStream(sample.Data, false));
                    waveStream   = disposables.AddAndReturn(new WaveFileReader(memoryStream));
                }
                else
                {
                    var path = WadSounds.TryGetSamplePath(level.Settings, sample.FileName);
                    if (path == null)
                    {
                        return;
                    }
                    else
                    {
                        waveStream = disposables.AddAndReturn(new WaveFileReader(path));
                    }
                }

                // Apply looping
                ISampleProvider sampleStream;
                if (loopCount <= 1)
                {
                    sampleStream = waveStream.ToSampleProvider();
                }
                else
                {
                    sampleStream = new RepeatedStream(waveStream)
                    {
                        LoopCount = loopCount
                    }
                };

                // Always play sample as 22 khz
                if (sampleStream.WaveFormat.SampleRate != 22050)
                {
                    sampleStream = new PitchedStream {
                        Source = sampleStream, Pitch = 22050.0f / sampleStream.WaveFormat.SampleRate
                    }
                }
                ;

                // Apply panning
                if (pan != 1.0f)
                {
                    sampleStream = new PanningSampleProvider(sampleStream)
                    {
                        Pan = pan
                    }
                }
                ;

                // Apply pitch
                if (pitch != 1.0f)
                {
                    sampleStream = new PitchedStream {
                        Source = sampleStream, Pitch = pitch
                    }
                }
                ;

                // Apply volume
                if (volume != 1.0f)
                {
                    sampleStream = new VolumeSampleProvider(sampleStream)
                    {
                        Volume = volume
                    }
                }
                ;

                // Add some silence to make sure the audio plays out.
                const int latencyInMilliseconds = 200;
                int       latencyInSamples      = (sampleStream.WaveFormat.SampleRate * latencyInMilliseconds * 2) / 1000;
                sampleStream = new OffsetSampleProvider(sampleStream)
                {
                    LeadOutSamples = sampleStream.WaveFormat.Channels * latencyInSamples
                };

                // Play
                _channels[channel] = disposables.AddAndReturn(new WaveOut());
                _channels[channel].Init(sampleStream);
                _channels[channel].PlaybackStopped += (s, e) =>
                {
                    foreach (IDisposable disposable in disposables)
                    {
                        disposable?.Dispose();
                    }
                    _channels[channel] = null;
                    _indices[channel]  = -1;
                };
                _channels[channel].Play();
            }
            catch (Exception ex)
            {
                // Clean up in case of a problem
                foreach (IDisposable disposable in disposables)
                {
                    disposable?.Dispose();
                }

                _logger.Error("Error while playing sample " + sample + ", exception: " + ex);
            }
        }
Example #2
0
        private static bool LoadSamples(ChunkReader chunkIO, ChunkId idOuter, Wad2 wad, ref Dictionary <long, WadSample> outSamples, bool obsolete)
        {
            if (idOuter != Wad2Chunks.Samples)
            {
                return(false);
            }

            var  samples       = new Dictionary <long, WadSample>();
            long obsoleteIndex = 0; // Move this into each chunk once we got rid of old style *.wad2 files.

            chunkIO.ReadChunks((id, chunkSize) =>
            {
                if (id != Wad2Chunks.Sample)
                {
                    return(false);
                }

                string FilenameObsolete = null;
                byte[] data             = null;

                chunkIO.ReadChunks((id2, chunkSize2) =>
                {
                    if (id2 == Wad2Chunks.SampleIndex)
                    {
                        obsoleteIndex = chunkIO.ReadChunkLong(chunkSize2);
                    }
                    else if (id2 == Wad2Chunks.SampleFilenameObsolete)
                    {
                        FilenameObsolete = chunkIO.ReadChunkString(chunkSize2);
                    }
                    else if (id2 == Wad2Chunks.SampleData)
                    {
                        data = chunkIO.ReadChunkArrayOfBytes(chunkSize2);
                    }
                    else
                    {
                        return(false);
                    }
                    return(true);
                });

                if (data == null && !string.IsNullOrEmpty(FilenameObsolete))
                {
                    string fullPath = Path.Combine(PathC.GetDirectoryNameTry(Assembly.GetEntryAssembly().Location), "Sounds\\TR4\\Samples", FilenameObsolete + ".wav");
                    data            = File.ReadAllBytes(fullPath);
                }

                samples.Add(obsoleteIndex++, new WadSample("", WadSample.ConvertSampleFormat(data,
                                                                                             sampleRate => obsolete ?
                                                                                             new WadSample.ResampleInfo {
                    Resample = false, SampleRate = WadSample.GameSupportedSampleRate
                } :
                                                                                             new WadSample.ResampleInfo {
                    Resample = true, SampleRate = sampleRate
                })));
                return(true);
            });

            outSamples = samples;
            return(true);
        }