private SoundHandle InsertChannel(Channel chan) { var index = -1; for (var i = 0; i != NumChannels; i++) { if (_channels[i] == null) { index = i; break; } } if (index == -1) { throw new InvalidOperationException("MixerImpl::out of mixer slots"); } _channels[index] = chan; var chanHandle = new SoundHandle { Value = index + _handleSeed * NumChannels }; chan.Handle = chanHandle; _handleSeed++; return(chanHandle); }
public bool IsSoundHandleActive(SoundHandle handle) { lock (_gate) { var index = handle.Value % NumChannels; return(_channels[index] != null && _channels[index].Handle.Value == handle.Value); } }
public int GetChannelVolume(SoundHandle handle) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) { return(0); } return(_channels[index].Volume); }
private Timestamp GetElapsedTime(SoundHandle handle) { lock (_gate) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) { return(new Timestamp(0, OutputRate)); } return(_channels[index].GetElapsedTime()); } }
public void SetChannelVolume(SoundHandle handle, int volume) { lock (_gate) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) { return; } _channels[index].Volume = volume; } }
public void SetChannelBalance(SoundHandle handle, int balance) { lock (_gate) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) { return; } _channels[index].Balance = balance; } }
public void PauseHandle(SoundHandle handle, bool paused) { lock (_gate) { // Simply ignore (un)pause requests for sounds that already terminated var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) { return; } _channels[index].Pause(paused); } }
public void StopHandle(SoundHandle handle) { lock (_gate) { // Simply ignore stop requests for handles of sounds that already terminated var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) { return; } _channels[index] = null; } }
public int GetChannelBalance(SoundHandle handle) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) return 0; return _channels[index].Balance; }
public int GetSoundElapsedTime(SoundHandle handle) { return(GetElapsedTime(handle).Milliseconds); }
SoundHandle StartTalkSound(int offset, int b, int mode) { Stream file; SoundHandle handle = new SoundHandle(); var id = -1; if (vm.Game.GameId == GameId.CurseOfMonkeyIsland) { sfxMode |= mode; return handle; } else if (vm.Game.GameId == GameId.Dig) { sfxMode |= mode; if (!(vm.Game.Features.HasFlag(GameFeatures.Demo))) return handle; throw new NotImplementedException(); } else { if (_sfxFilename == null) { // Console.Error.WriteLine("StartTalkSound: SFX file not found"); return handle; } // Some games frequently assume that starting one sound effect will // automatically stop any other that may be playing at that time. So // that is what we do here, but we make an exception for speech. if (mode == 1 && (vm.Game.GameId == GameId.Tentacle || vm.Game.GameId == GameId.SamNMax)) { id = 777777 + _talkSoundChannel; _mixer.StopID(id); } int num = 0; if (b > 8) { num = (b - 8) >> 1; } offset += 8; _mouthSyncTimes = new ushort[num + 1]; file = ServiceLocator.FileStorage.OpenFileRead(_sfxFilename); var br = new BinaryReader(file); file.Seek(offset, SeekOrigin.Begin); for (int i = 0; i < num; i++) { _mouthSyncTimes[i] = br.ReadUInt16BigEndian(); } // Adjust offset to account for the mouth sync times. It is noteworthy // that we do not adjust the size here for compressed streams, since // they only set size to the size of the compressed sound data. offset += num * 2; // TODO: In case we ever set up the size for VOC streams, we should // really check whether the size contains the _mouthSyncTimes. // if (SoundMode == SoundMode.VOCMode) // size -= num * 2; _mouthSyncTimes[num] = 0xFFFF; sfxMode |= mode; _curSoundPos = 0; _mouthSyncMode = true; } var input = new VocStream(file, true); var iMuseDigital = vm.MusicEngine as IMuseDigital; if (iMuseDigital != null) { iMuseDigital.StartVoice(TalkSoundID, input); } else { if (mode == 1) { handle = _mixer.PlayStream(SoundType.SFX, input, id); } else { handle = _mixer.PlayStream(SoundType.Speech, input, id); } } return handle; }
public bool StartSpeech(ushort textNum) { if (!SystemVars.Instance.SystemFlags.HasFlag(SystemFlags.AllowSpeech)) return false; var speechFileNum = (ushort)(_speechConvertTable[textNum >> 12] + (textNum & 0xFFF)); var speechData = _skyDisk.LoadFile(speechFileNum + 50000); if (speechData == null) { // TODO: debug(9, "File %d (speechFile %d from section %d) wasn't found", speechFileNum + 50000, textNum & 0xFFF, textNum >> 12); return false; } var header = ServiceLocator.Platform.ToStructure<DataFileHeader>(speechData, 0); var speechSize = header.s_tot_size - ServiceLocator.Platform.SizeOf<DataFileHeader>(); var playBuffer = new byte[speechSize]; Array.Copy(speechData, ServiceLocator.Platform.SizeOf<DataFileHeader>(), playBuffer, 0, speechSize); // Workaround for BASS bug #897775 - some voice-overs are played at // half speed in 0.0368 (the freeware CD version), in 0.0372 they sound // just fine. int rate; if (_skyDisk.DetermineGameVersion().Version.Minor == 368 && (textNum == 20905 || textNum == 20906)) rate = 22050; else rate = 11025; _mixer.StopID(SoundSpeech); var stream = new RawStream(AudioFlags.Unsigned, rate, true, new MemoryStream(playBuffer, 0, speechSize)); _ingameSpeech = _mixer.PlayStream(SoundType.Speech, stream, SoundSpeech); return true; }
// TODO: public void Start(Timestamp limit) { Stop(); throw new NotImplementedException(); var stream = AudioStream; if (stream == null) throw new InvalidOperationException("stream should not be null"); // stream = new LimitingAudioStream(stream, limit, false); _handle = Mixer.PlayStream(SoundType, stream, -1, _muted ? 0 : Volume, Balance, true); // Pause the audio again if we're still paused if (IsPaused) Mixer.PauseHandle(_handle, true); }
public void StopHandle(SoundHandle handle) { lock (_gate) { // Simply ignore stop requests for handles of sounds that already terminated var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) return; _channels[index] = null; } }
public void SetChannelBalance(SoundHandle handle, int balance) { lock (_gate) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) return; _channels[index].Balance = balance; } }
public void SetChannelVolume(SoundHandle handle, int volume) { lock (_gate) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) return; _channels[index].Volume = volume; } }
public int GetSoundElapsedTime(SoundHandle handle) { return GetElapsedTime(handle).Milliseconds; }
public void PauseHandle(SoundHandle handle, bool paused) { lock (_gate) { // Simply ignore (un)pause requests for sounds that already terminated var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) return; _channels[index].Pause(paused); } }
public bool IsSoundHandleActive(SoundHandle handle) { lock (_gate) { var index = handle.Value % NumChannels; return _channels[index] != null && _channels[index].Handle.Value == handle.Value; } }
private Timestamp GetElapsedTime(SoundHandle handle) { lock (_gate) { var index = handle.Value % NumChannels; if (_channels[index] == null || _channels[index].Handle.Value != handle.Value) return new Timestamp(0, OutputRate); return _channels[index].GetElapsedTime(); } }
private SoundHandle InsertChannel(Channel chan) { var index = -1; for (var i = 0; i != NumChannels; i++) { if (_channels[i] == null) { index = i; break; } } if (index == -1) { throw new InvalidOperationException("MixerImpl::out of mixer slots"); } _channels[index] = chan; var chanHandle = new SoundHandle { Value = index + _handleSeed * NumChannels }; chan.Handle = chanHandle; _handleSeed++; return chanHandle; }
public bool StartSpeech(ushort roomNo, ushort localNo) { if (_cowHeader == null || ServiceLocator.AudioManager == null) { // TODO: warning("Sound::startSpeech: COW file isn't open"); return false; } uint locIndex = 0xFFFFFFFF; int sampleSize = 0; uint index = 0; // if (_cowMode == CowPSX) // { // Common::File file; // uint16 i; // if (!file.open("speech.lis")) // { // warning("Could not open speech.lis"); // return false; // } // for (i = 0; !file.eos() && !file.err(); i++) // if (file.readUint16LE() == roomNo) // { // locIndex = i; // break; // } // file.close(); // if (locIndex == 0xFFFFFFFF) // { // warning("Could not find room %d in speech.lis", roomNo); // return false; // } // if (!file.open("speech.inf")) // { // warning("Could not open speech.inf"); // return false; // } // uint16 numRooms = file.readUint16LE(); // Read number of rooms referenced in this file // file.seek(locIndex * 4 + 2); // 4 bytes per room, skip first 2 bytes // uint16 numLines = file.readUint16LE(); // uint16 roomOffset = file.readUint16LE(); // file.seek(2 + numRooms * 4 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the room indexes too. // locIndex = 0xFFFFFFFF; // for (i = 0; i < numLines; i++) // if (file.readUint16LE() == localNo) // { // locIndex = i; // break; // } // if (locIndex == 0xFFFFFFFF) // { // warning("Could not find local number %d in room %d in speech.inf", roomNo, localNo); // return false; // } // file.close(); // index = _cowHeader[(roomOffset + locIndex) * 2]; // sampleSize = _cowHeader[(roomOffset + locIndex) * 2 + 1]; // } // else { locIndex = _cowHeader[roomNo] >> 2; sampleSize = (int)_cowHeader[(int)(locIndex + (localNo * 2))]; index = _cowHeader[(int)(locIndex + (localNo * 2) - 1)]; // } // debug(6, "startSpeech(%d, %d): locIndex %d, sampleSize %d, index %d", roomNo, localNo, locIndex, sampleSize, index); IAudioStream stream = null; if (sampleSize != 0) { byte speechVol = (byte)((_speechVolR + _speechVolL) / 2); sbyte speechPan = (sbyte)((_speechVolR - _speechVolL) / 2); if ((_cowMode == CowMode.CowWave) || (_cowMode == CowMode.CowDemo)) { uint size; var data = UncompressSpeech(index + _cowHeaderSize, (uint)sampleSize, out size); if (data != null) { stream = new RawStream(SPEECH_FLAGS, 11025, true, new MemoryStream(data.Data, data.Offset, (int)size)); _speechHandle = _mixer.PlayStream(SoundType.Speech, stream, SOUND_SPEECH_ID, speechVol, speechPan); } } // else if (_cowMode == CowPSX && sampleSize != 0xffffffff) // { // _cowFile.seek(index * 2048); // Common::SeekableReadStream* tmp = _cowFile.readStream(sampleSize); // assert(tmp); // stream = Audio::makeXAStream(tmp, 11025); // _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan); // // with compressed audio, we can't calculate the wave volume. // // so default to talking. // for (int cnt = 0; cnt < 480; cnt++) // _waveVolume[cnt] = true; // _waveVolPos = 0; // } else if (_cowMode == CowMode.CowFLAC) { _cowFile.BaseStream.Seek(index, SeekOrigin.Begin); var tmp = _cowFile.ReadBytes(sampleSize); stream = ServiceLocator.AudioManager.MakeFlacStream(new MemoryStream(tmp)); if (stream != null) { _speechHandle = _mixer.PlayStream(SoundType.Speech, stream, SOUND_SPEECH_ID, speechVol, speechPan); // with compressed audio, we can't calculate the wave volume. // so default to talking. for (int cnt = 0; cnt < 480; cnt++) _waveVolume[cnt] = true; _waveVolPos = 0; } } else if (_cowMode == CowMode.CowVorbis) { _cowFile.BaseStream.Seek(index, SeekOrigin.Begin); var tmp = _cowFile.ReadBytes(sampleSize); stream = ServiceLocator.AudioManager.MakeVorbisStream(new MemoryStream(tmp)); if (stream != null) { _speechHandle = _mixer.PlayStream(SoundType.Speech, stream, SOUND_SPEECH_ID, speechVol, speechPan); // with compressed audio, we can't calculate the wave volume. // so default to talking. for (int cnt = 0; cnt < 480; cnt++) _waveVolume[cnt] = true; _waveVolPos = 0; } } else if (_cowMode == CowMode.CowMP3) { _cowFile.BaseStream.Seek(index, SeekOrigin.Begin); var tmp = _cowFile.ReadBytes(sampleSize); stream = ServiceLocator.AudioManager.MakeMp3Stream(new MemoryStream(tmp)); if (stream != null) { _speechHandle = _mixer.PlayStream(SoundType.Speech, stream, SOUND_SPEECH_ID, speechVol, speechPan); // with compressed audio, we can't calculate the wave volume. // so default to talking. for (int cnt = 0; cnt < 480; cnt++) _waveVolume[cnt] = true; _waveVolPos = 0; } } return true; } else return false; }
public void Clear() { TrackId = 0; pan = 0; vol = 0; VolFadeDest = 0; VolFadeStep = 0; VolFadeDelay = 0; VolFadeUsed = false; // SoundId = 0; SoundName = null; Used = false; ToBeRemoved = false; SouStreamUsed = false; SndDataExtComp = false; SoundPriority = 0; RegionOffset = 0; DataOffset = 0; CurRegion = 0; CurHookId = 0; VolGroupId = 0; SoundType = 0; FeedSize = 0; DataMod12Bit = 0; MixerFlags = AudioFlags.None; SoundDesc = null; MixChanHandle = new SoundHandle(); Stream = null; }
public Music(IMixer mixer, string directory) { _mixer = mixer; _sampleRate = mixer.OutputRate; _volumeL = _volumeR = 192; _soundHandle = _mixer.PlayStream(SoundType.Plain, this, -1, Mixer.MaxChannelVolume, 0, false, true); _handles = new MusicHandle[2]; for (int i = 0; i < _handles.Length; i++) { _handles[i] = new MusicHandle(directory); } }
public void PlaySound(ushort sound, ushort volume, byte channel) { if (channel == 0) _mixer.StopID(SoundChannel0); else _mixer.StopID(SoundChannel1); if (_soundData == null) { // TODO: warning //warning("Sound::playSound(%04X, %04X) called with a section having been loaded", sound, volume); return; } if (sound > _soundsTotal) { // TODO: debug //debug(5, "Sound::playSound %d ignored, only %d sfx in file", sound, _soundsTotal); return; } volume = (ushort)((volume & 0x7F) << 1); sound &= 0xFF; // Note: All those tables are big endian. Don't ask me why. *sigh* // Use the sample rate from game data, see bug #1507757. var sampleRate = _sampleRates.Data.ToUInt16BigEndian(_sampleRates.Offset + (sound << 2)); if (sampleRate > 11025) sampleRate = 11025; var dataOfs = ScummHelper.SwapBytes(_sfxInfo[((sound << 3) + 0) / 2]) << 4; int dataSize = ScummHelper.SwapBytes(_sfxInfo[((sound << 3) + 2) / 2]); int dataLoop = ScummHelper.SwapBytes(_sfxInfo[((sound << 3) + 6) / 2]); dataOfs += _sfxBaseOfs; var stream = new RawStream(AudioFlags.Unsigned, sampleRate, false, new MemoryStream(_soundData, dataOfs, dataSize)); IAudioStream output; if (dataLoop != 0) { var loopSta = dataSize - dataLoop; var loopEnd = dataSize; output = new SubLoopingAudioStream(stream, 0, new Timestamp(0, loopSta, sampleRate), new Timestamp(0, loopEnd, sampleRate), true); } else { output = stream; } if (channel == 0) _ingameSound0 = _mixer.PlayStream(SoundType.SFX, output, SoundChannel0, volume, 0); else _ingameSound1 = _mixer.PlayStream(SoundType.SFX, output, SoundChannel1, volume, 0); }