public unsafe int DecodePCM(SoundSample sample, int sampleOffset44k, int sampleCount44k, float *dest) { lastFormat = WAVE_FORMAT_TAG.PCM; lastSample = sample; var shift = 22050 / sample.objectInfo.nSamplesPerSec; var sampleOffset = sampleOffset44k >> shift; var sampleCount = sampleCount44k >> shift; if (sample.nonCacheData == null) { Debug.Assert(false); failed = true; return(0); } // this should never happen ( note: I've seen that happen with the main thread down in idGameLocal::MapClear clearing entities - TTimo ) if (!sample.FetchFromCache(sampleOffset * sizeof(short), out var first, out var pos, out var size, false)) { failed = true; return(0); } var readSamples = size - pos < sampleCount * sizeof(short) ? (size - pos) / sizeof(short) : sampleCount; // duplicate samples for 44kHz output fixed(byte *_ = &first.v[first.o + pos]) Simd.UpSamplePCMTo44kHz(dest, (short *)_, readSamples, sample.objectInfo.nSamplesPerSec, sample.objectInfo.nChannels); return(readSamples << shift); }
OggVorbis_File ogg; // OggVorbis file public unsafe virtual void Decode(SoundSample sample, int sampleOffset44k, int sampleCount44k, float *dest) { if (sample.objectInfo.wFormatTag != lastFormat || sample != lastSample) { ClearDecoder(); } lastDecodeTime = soundSystemLocal.CurrentSoundTime; if (failed) { UnsafeX.InitBlock(dest, 0, sampleCount44k * sizeof(float)); return; } // samples can be decoded both from the sound thread and the main thread for shakes ISystem.EnterCriticalSection(CRITICAL_SECTION.SECTION_ONE); var readSamples44k = sample.objectInfo.wFormatTag switch { WAVE_FORMAT_TAG.PCM => DecodePCM(sample, sampleOffset44k, sampleCount44k, dest), WAVE_FORMAT_TAG.OGG => DecodeOGG(sample, sampleOffset44k, sampleCount44k, dest), _ => 0, }; ISystem.LeaveCriticalSection(CRITICAL_SECTION.SECTION_ONE); if (readSamples44k < sampleCount44k) { UnsafeX.InitBlock(dest + readSamples44k, 0, (sampleCount44k - readSamples44k) * sizeof(float)); } }
/// <summary> /// Initializes sound files. /// </summary> public static void Initialize(IGameConfig config) { int id = 0; Clear1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Clear1.mp3")); Clear2 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Clear2.mp3")); Click1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Click1.mp3")); Click2 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Click2.mp3")); Click3 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Click3.mp3")); Error1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Error1.mp3")); Explode1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Explode1.mp3")); Explode2 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Explode2.mp3")); Explode3 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Explode3.mp3")); Hit1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Hit1.mp3")); Hit2 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Hit2.mp3"), 0.8f); LevelUp1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "LevelUp1.mp3")); MenuBack1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "MenuBack1.mp3")); MenuMove1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "MenuMove1.mp3")); MenuMove2 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "MenuMove2.mp3")); MenuSelect1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "MenuSelect1.mp3")); MenuSelect2 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "MenuSelect2.mp3")); Music1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Music1.mp3"), 0.1f, true); Music2 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Music2.mp3"), 0.2f, true); Send1 = new SoundSample(++id, Path.Combine(config.AudioSampleFolder, "Send1.mp3")); }
public void SingleSound(SoundSample sound) { switch (sound) { case SoundSample.explosion: source.PlayOneShot(explosion, 1.0f); break; case SoundSample.drink: source.PlayOneShot(drink, 1.0f); break; case SoundSample.mix: source.PlayOneShot(mix, 1.0f); break; case SoundSample.die_enemy: source.PlayOneShot(die_enemy, 0.6f); break; case SoundSample.hit_player: source.PlayOneShot(hit_player, 1.0f); break; case SoundSample.die_player: source.PlayOneShot(die_player, 1.0f); break; } }
/// <summary> /// Plays the specified sound sample, looping until stop. /// Stops any existing loop. /// </summary> public static void Loop(SoundSample sound, long position = 0) { if (sound == Sound.Music1) { _musicMode = MusicMode.Music1; } else if (sound == Sound.Music2) { _musicMode = MusicMode.Music2; } else { _musicMode = MusicMode.None; } if ((sound.IsMusic) && (!GameConfig.Instance.Music)) { return; } if ((!sound.IsMusic) && (!GameConfig.Instance.SoundEffects)) { return; } _manager?.PlayLoop(id: sound.ID, stopOtherLoops: true, position: position); }
public void Clear() { failed = false; lastFormat = WAVE_FORMAT_TAG.PCM; lastSample = null; lastSampleOffset = 0; lastDecodeTime = 0; }
public void playOnce(string file) { SoundSample snd = new SoundSample(this, file, file, 1, false); snd.playonce = true; soundSamples[file] = snd; play(file); }
/// <summary> /// Plays the specified sound sample. /// </summary> public static void Play(SoundSample sound) { if ((sound.IsMusic) && (!GameConfig.Instance.Music)) { return; } if ((!sound.IsMusic) && (!GameConfig.Instance.SoundEffects)) { return; } _manager?.PlaySound(sound.ID); }
public List <string> getPlayingSamples() { List <string> samples = new List <string>(); foreach (KeyValuePair <string, SoundSample> sample in soundSamples) { SoundSample snd = sample.Value; if (snd.playing) { samples.Add(snd.name); } } return(samples); }
// Update is called once per frame void Update() { List <string> removes = new List <string>(); foreach (KeyValuePair <string, SoundSample> sample in soundSamples) { SoundSample snd = sample.Value; if (snd.playing) { snd.tick(); snd.checkInjects(); if (snd.checkFinished()) { finished.Invoke(snd.name); //Debug.Log("yes, in update finish "+snd.name); if (snd.callback != null) { Debug.Log("execute callback !" + snd.callback); if (snd.callbackName != null) { snd.callback(snd.callbackName, "completed"); } else { snd.callback(snd.name, "completed"); } //snd.callback = null; } if (snd.playonce) { removes.Add(sample.Key); } } } } foreach (string remove in removes) { soundSamples.Remove(remove); } }
private void FromStream(StreamReader reader) { if (reader.ReadLine() != "soundsfile version 3") { throw new Exception("可能不支持当前mod或该mod已损坏"); } Samples = new List <SoundSample>(Convert.ToInt32(reader.ReadLine())); string[] s = reader.ReadToEnd().Split(new string[] { " ", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries); int j = 0; for (int i = 0; i < Samples.Capacity; i++) { var smp = SoundSample.FromString(Module, s, ref j); Samples.Add(smp); } Sounds = new List <Sound>(Convert.ToInt32(s[j++])); for (int i = 0; i < Sounds.Capacity; i++) { var snd = Sound.FromString(Module, s, ref j); Sounds.Add(snd); } }
public void Clear() { Stop(); soundShader = null; lastVolume = 0f; triggerChannel = ISoundSystem.SCHANNEL_ANY; channelFade.Clear(); diversity = 0f; leadinSample = null; trigger44kHzTime = 0; stopped = false; for (var j = 0; j < 6; j++) { lastV[j] = 0f; } parms.memset(); triggered = false; openalSource = 0; openalStreamingOffset = 0; openalStreamingBuffer[0] = openalStreamingBuffer[1] = openalStreamingBuffer[2] = 0; lastopenalStreamingBuffer[0] = lastopenalStreamingBuffer[1] = lastopenalStreamingBuffer[2] = 0; }
public unsafe int DecodeOGG(SoundSample sample, int sampleOffset44k, int sampleCount44k, float *dest) { int readSamples, totalSamples; var shift = 22050 / sample.objectInfo.nSamplesPerSec; var sampleOffset = sampleOffset44k >> shift; var sampleCount = sampleCount44k >> shift; // open OGG file if not yet opened if (lastSample == null) { // make sure there is enough space for another decoder if (ISampleDecoder.decoderMemoryAllocator.FreeBlockMemory < ISampleDecoder.MIN_OGGVORBIS_MEMORY) { return(0); } if (sample.nonCacheData == null) { Debug.Assert(false); failed = true; return(0); } // this should never happen file.SetData(sample.nonCacheData, sample.objectMemSize); if (OggVorbis.ov_openFile(file, ogg) < 0) { failed = true; return(0); } lastFormat = WAVE_FORMAT_TAG.OGG; lastSample = sample; } // seek to the right offset if necessary if (sampleOffset != lastSampleOffset && ov_pcm_seek(ogg, sampleOffset / sample.objectInfo.nChannels) != 0) { failed = true; return(0); } lastSampleOffset = sampleOffset; // decode OGG samples totalSamples = sampleCount; readSamples = 0; do { float **samples; var ret = (int)ov_read_float(ogg, &samples, totalSamples / sample.objectInfo.nChannels, null); if (ret == 0) { failed = true; break; } if (ret < 0) { failed = true; return(0); } ret *= sample.objectInfo.nChannels; Simd.UpSampleOGGTo44kHz(dest + (readSamples << shift), samples, ret, sample.objectInfo.nSamplesPerSec, sample.objectInfo.nChannels); readSamples += ret; totalSamples -= ret; } while (totalSamples > 0); lastSampleOffset += readSamples; return(readSamples << shift); }
public void addSample(string name, string sample, float volume = 1, bool loop = false) { SoundSample snd = new SoundSample(this, name, sample, volume, loop); soundSamples[name] = snd; }
/// <summary> /// Returns current position in specified looping sound, or 0 if not looping sound. /// </summary> public static long GetLoopPosition(SoundSample sound) { return(_manager?.GetLoopPosition(sound.ID) ?? 0); }
/// <summary> /// Stops specified sound, if it's looping. Returns current position (if possible), or 0. /// </summary> public static long StopLoop(SoundSample sound) { return(_manager?.StopLoop(sound.ID) ?? 0); }