private async Task CreateEmitter(int spatialSoundIdx) { if (_graph == null) { return; } //Create the AudioNodeEmitter AudioNodeEmitter emitter = new AudioNodeEmitter( AudioNodeEmitterShape.CreateOmnidirectional(), AudioNodeEmitterDecayModels.CreateNatural(), AudioNodeEmitterSettings.None); emitter.Position = _spatialSounds[spatialSoundIdx].Position; //Create a new AudioFileInputNode and add an emitter to it var audio = await GetSoundFileAsync(spatialSoundIdx); CreateAudioFileInputNodeResult inCreateResult = await _graph.CreateFileInputNodeAsync(audio, emitter); inCreateResult.FileInputNode.OutgoingGain = 5; // _spatialSounds[_spatialSoundsIdx].Gain; //Add the new AudioFileInputNode to the AudioGraph inCreateResult.FileInputNode.AddOutgoingConnection(_deviceOutput); inCreateResult.FileInputNode.AddOutgoingConnection(_submixNode); //Subscribe to the FileCompleted event so that we can go to the next spatial sound //inCreateResult.FileInputNode.FileCompleted += CurrentAudioFileInputNode_FileCompleted; if (_currentAudioFileInputNode != null && _currentAudioFileInputNode.OutgoingConnections.Count > 0) { //Remove the old AudioFileOutputNode from the AudioGraph _currentAudioFileInputNode.RemoveOutgoingConnection(_deviceOutput); _currentAudioFileInputNode.RemoveOutgoingConnection(_submixNode); } //Set the current node _currentAudioFileInputNode = inCreateResult.FileInputNode; }
private async void SecondFileButtonClick(object sender, RoutedEventArgs e) { if (_second == null) { var fileInputNodeResult = await SelectInputFile(); _second = fileInputNodeResult.FileInputNode; _second.AddOutgoingConnection(_subMixNode); SecondFileButton.Content = "Stop second file"; } else if (_second.OutgoingConnections.Count >= 1) { _second.RemoveOutgoingConnection(_subMixNode); SecondFileButton.Content = "Resume second file"; } else { _second.AddOutgoingConnection(_subMixNode); SecondFileButton.Content = "Stop second file"; } }
// Async Speak output of a text private async Task PlayAsyncLow(SoundBite soundBite) { _playing = true; // locks additional calls for Speak until finished talking this bit if (!_canPlay || _audioGraph == null || _deviceOutputNode == null) { LOG.LogError($"PlayAsyncLow: Some items do not exist: cannot play..\n [{_audioGraph}] [{_deviceOutputNode}]"); await EndOfSound( ); return; } // don't reload if the sound is already in use if (soundBite.Melody != _soundInUse?.Melody) { // if a prev. Node exists, remove it if (_fileInputNode != null) { _audioGraph.Stop( ); _fileInputNode.FileCompleted -= _fileInputNode_FileCompleted; _fileInputNode.RemoveOutgoingConnection(_deviceOutputNode); _fileInputNode.Dispose( ); _fileInputNode = null; } // set new sound _sound = _installedSounds.Where(x => x.Melody == soundBite.Melody).FirstOrDefault( ); if (_sound == null) { LOG.LogError($"PlayAsyncLow: Melody has no Audiofile: {soundBite.Melody} - cannot play"); await EndOfSound( ); return; } StorageFile file = await StorageFile.CreateStreamedFileAsync($"{_sound.Id}.{_sound.SType}", StreamedFileWriter, null); // create the InputNode var resultAF = await _audioGraph.CreateFileInputNodeAsync(file); if (resultAF.Status != AudioFileNodeCreationStatus.Success) { LOG.LogError($"PlayAsyncLow: AudioFileNodeCreationStatus creation: {resultAF.Status}" + $"\nExtError: {resultAF.ExtendedError}"); await EndOfSound( ); return; } _fileInputNode = resultAF.FileInputNode; _fileInputNode.FileCompleted += _fileInputNode_FileCompleted; _fileInputNode.AddOutgoingConnection(_deviceOutputNode); _audioGraph.Start( ); _soundInUse = _sound.AsCopy( ); } // we capture problems through Exceptions here - the settings and restrictions seem not complete in the Docs try { // Play it // cannot start after prev end - so set it null and seek to start of file _fileInputNode.StartTime = null; _fileInputNode.EndTime = null; // cannot start after prev end - so set it null _fileInputNode.Seek(new TimeSpan(0)); // have to seek to Start, we cannot assign a StartTime before the current Position // only now we can set any new start and end... (that is not in the documents...) _fileInputNode.StartTime = TimeSpan.FromSeconds(soundBite.Tone * _soundInUse.ToneStep_sec); _fileInputNode.EndTime = _fileInputNode.StartTime + TimeSpan.FromSeconds((soundBite.Duration < 0) ? _soundInUse.ToneDuration_sec : soundBite.Duration); _fileInputNode.OutgoingGain = soundBite.Volume; _fileInputNode.LoopCount = (int)soundBite.Loops; // counts down in the Completed Callback - track completeness there (not in docu...) _fileInputNode.PlaybackSpeedFactor = soundBite.SpeedFact; // Plays in the current Thread - cannot be waited for in the same thread _fileInputNode.Start( ); //_audioGraph.Start( ); } catch (Exception e) { LOG.LogError($"PlayAsyncLow: Sample Setup caused an Exception\n{e.Message}"); await EndOfSound( ); } }