private Collection <RecognizedPhrase> ExtractAlternates(int numberOfAlternates, bool isSapi53Header) { Collection <RecognizedPhrase> alternates = new(); if (numberOfAlternates > 0) { GCHandle gc = GCHandle.Alloc(_sapiAlternatesBlob, GCHandleType.Pinned); try { IntPtr buffer = gc.AddrOfPinnedObject(); int sizeOfSpSerializedPhraseAlt = Marshal.SizeOf <SPSERIALIZEDPHRASEALT>(); int offset = 0; for (int i = 0; i < numberOfAlternates; i++) { IntPtr altBuffer = new((long)buffer + offset); SPSERIALIZEDPHRASEALT alt = Marshal.PtrToStructure <SPSERIALIZEDPHRASEALT>(altBuffer); offset += sizeOfSpSerializedPhraseAlt; // advance over SPSERIALIZEDPHRASEALT if (isSapi53Header) { offset += (int)((alt.cbAltExtra + 7) & ~7); // advance over extra data with alignment padding } else { offset += (int)alt.cbAltExtra; // no alignment padding } // we cannot use a constructor parameter because RecognitionResult also derives from RecognizedPhrase IntPtr phraseBuffer = new((long)buffer + offset); SPSERIALIZEDPHRASE serializedPhrase = RecognizedPhrase.GetPhraseHeader(phraseBuffer, _header.ulPhraseAltDataSize - (uint)offset, _isSapi53Header); int serializedPhraseSize = (int)serializedPhrase.ulSerializedSize; RecognizedPhrase phrase = new(); // Get the alphabet of the raw phrase alternate, which should be the same as the engine bool hasIPAPronunciation = (_header.fAlphabet & (uint)SPRESULTALPHABET.SPRA_ENGINE_UPS) != 0; phrase.InitializeFromSerializedBuffer(this, serializedPhrase, phraseBuffer, serializedPhraseSize, isSapi53Header, hasIPAPronunciation); if (isSapi53Header) { offset += ((serializedPhraseSize + 7) & ~7); // advance over phrase with alignment padding } else { offset += serializedPhraseSize; // advance over phrase } alternates.Add(phrase); } } finally { gc.Free(); } } return(alternates); }
private void Initialize(IRecognizerInternal recognizer, ISpRecoResult recoResult, byte[] sapiResultBlob, int maxAlternates) { _recognizer = recognizer; _maxAlternates = maxAlternates; try { _sapiRecoResult = (recoResult as ISpRecoResult2); } catch (COMException) { _sapiRecoResult = null; } GCHandle gCHandle = GCHandle.Alloc(sapiResultBlob, GCHandleType.Pinned); try { IntPtr intPtr = gCHandle.AddrOfPinnedObject(); int num = Marshal.ReadInt32(intPtr, 4); if (num == Marshal.SizeOf(typeof(SPRESULTHEADER_Sapi51))) { SPRESULTHEADER_Sapi51 source = (SPRESULTHEADER_Sapi51)Marshal.PtrToStructure(intPtr, typeof(SPRESULTHEADER_Sapi51)); _header = new SPRESULTHEADER(source); _isSapi53Header = false; } else { _header = (SPRESULTHEADER)Marshal.PtrToStructure(intPtr, typeof(SPRESULTHEADER)); _isSapi53Header = true; } _header.Validate(); IntPtr phraseBuffer = new IntPtr((long)intPtr + (int)_header.ulPhraseOffset); SPSERIALIZEDPHRASE phraseHeader = RecognizedPhrase.GetPhraseHeader(phraseBuffer, _header.ulPhraseDataSize, _isSapi53Header); bool hasIPAPronunciation = (_header.fAlphabet & 1) != 0; InitializeFromSerializedBuffer(this, phraseHeader, phraseBuffer, (int)_header.ulPhraseDataSize, _isSapi53Header, hasIPAPronunciation); if (recoResult != null) { ExtractDictationAlternates(recoResult, maxAlternates); recoResult.Discard(255u); } } finally { gCHandle.Free(); } _sapiAudioBlob = new byte[_header.ulRetainedDataSize]; Array.Copy(sapiResultBlob, (int)_header.ulRetainedOffset, _sapiAudioBlob, 0, (int)_header.ulRetainedDataSize); _sapiAlternatesBlob = new byte[_header.ulPhraseAltDataSize]; Array.Copy(sapiResultBlob, (int)_header.ulPhraseAltOffset, _sapiAlternatesBlob, 0, (int)_header.ulPhraseAltDataSize); }
private void ExtractDictationAlternates(ISpRecoResult recoResult, int maxAlternates) { if (recoResult != null && base.Grammar is DictationGrammar) { _alternates = new Collection <RecognizedPhrase>(); IntPtr[] array = new IntPtr[maxAlternates]; try { recoResult.GetAlternates(0, -1, maxAlternates, array, out maxAlternates); } catch (COMException) { maxAlternates = 0; } for (uint num = 0u; num < maxAlternates; num++) { ISpPhraseAlt spPhraseAlt = (ISpPhraseAlt)Marshal.GetObjectForIUnknown(array[num]); try { IntPtr ppCoMemPhrase; spPhraseAlt.GetSerializedPhrase(out ppCoMemPhrase); try { RecognizedPhrase recognizedPhrase = new RecognizedPhrase(); SPSERIALIZEDPHRASE phraseHeader = RecognizedPhrase.GetPhraseHeader(ppCoMemPhrase, uint.MaxValue, _isSapi53Header); bool hasIPAPronunciation = (_header.fAlphabet & 1) != 0; recognizedPhrase.InitializeFromSerializedBuffer(this, phraseHeader, ppCoMemPhrase, (int)phraseHeader.ulSerializedSize, _isSapi53Header, hasIPAPronunciation); _alternates.Add(recognizedPhrase); } finally { Marshal.FreeCoTaskMem(ppCoMemPhrase); } } finally { Marshal.Release(array[num]); } } } }
private Collection <RecognizedPhrase> ExtractAlternates(int numberOfAlternates, bool isSapi53Header) { Collection <RecognizedPhrase> collection = new Collection <RecognizedPhrase>(); if (numberOfAlternates > 0) { GCHandle gCHandle = GCHandle.Alloc(_sapiAlternatesBlob, GCHandleType.Pinned); try { IntPtr value = gCHandle.AddrOfPinnedObject(); int num = Marshal.SizeOf(typeof(SPSERIALIZEDPHRASEALT)); int num2 = 0; for (int i = 0; i < numberOfAlternates; i++) { IntPtr ptr = new IntPtr((long)value + num2); SPSERIALIZEDPHRASEALT sPSERIALIZEDPHRASEALT = (SPSERIALIZEDPHRASEALT)Marshal.PtrToStructure(ptr, typeof(SPSERIALIZEDPHRASEALT)); num2 += num; num2 = ((!isSapi53Header) ? (num2 + (int)sPSERIALIZEDPHRASEALT.cbAltExtra) : (num2 + (int)((sPSERIALIZEDPHRASEALT.cbAltExtra + 7) & -8))); IntPtr phraseBuffer = new IntPtr((long)value + num2); SPSERIALIZEDPHRASE phraseHeader = RecognizedPhrase.GetPhraseHeader(phraseBuffer, (uint)((int)_header.ulPhraseAltDataSize - num2), _isSapi53Header); int ulSerializedSize = (int)phraseHeader.ulSerializedSize; RecognizedPhrase recognizedPhrase = new RecognizedPhrase(); bool hasIPAPronunciation = (_header.fAlphabet & 2) != 0; recognizedPhrase.InitializeFromSerializedBuffer(this, phraseHeader, phraseBuffer, ulSerializedSize, isSapi53Header, hasIPAPronunciation); num2 = ((!isSapi53Header) ? (num2 + ulSerializedSize) : (num2 + ((ulSerializedSize + 7) & -8))); collection.Add(recognizedPhrase); } return(collection); } finally { gCHandle.Free(); } } return(collection); }
private void ExtractDictationAlternates(ISpRecoResult recoResult, int maxAlternates) { // Get the alternates for dictation // alternates for dictation are not part of the recognition results and must be pulled out // from the recognition result bits. if (recoResult != null) // recoResult is null if we are in the case of our unit test. { if (Grammar is DictationGrammar) { _alternates = new Collection <RecognizedPhrase>(); IntPtr[] sapiAlternates = new IntPtr[maxAlternates]; try { recoResult.GetAlternates(0, -1, maxAlternates, sapiAlternates, out maxAlternates); } catch (COMException) { // In some cases such as when the dictation grammar has been unloaded, the engine may not be able // to provide the alternates. We set the alternate list to empty. maxAlternates = 0; } //InnerList.Capacity = (int)numSapiAlternates; for (uint i = 0; i < maxAlternates; i++) { ISpPhraseAlt phraseAlt = (ISpPhraseAlt)Marshal.GetObjectForIUnknown(sapiAlternates[i]); try { IntPtr coMemSerializedPhrase; phraseAlt.GetSerializedPhrase(out coMemSerializedPhrase); try { // Build a recognition phrase result RecognizedPhrase phrase = new(); // we cannot use a constructor parameter because RecognitionResult also derives from RecognizedPhrase SPSERIALIZEDPHRASE serializedPhrase = RecognizedPhrase.GetPhraseHeader(coMemSerializedPhrase, uint.MaxValue, _isSapi53Header); // // If we are getting the alternates from SAPI, the alphabet should have already been converted // to the alphabet we (applications) want. // bool hasIPAPronunciation = (_header.fAlphabet & (uint)SPRESULTALPHABET.SPRA_APP_UPS) != 0; phrase.InitializeFromSerializedBuffer(this, serializedPhrase, coMemSerializedPhrase, (int)serializedPhrase.ulSerializedSize, _isSapi53Header, hasIPAPronunciation); _alternates.Add(phrase); } finally { Marshal.FreeCoTaskMem(coMemSerializedPhrase); } } finally { Marshal.Release(sapiAlternates[i]); } } } } }
private void Initialize(IRecognizerInternal recognizer, ISpRecoResult recoResult, byte[] sapiResultBlob, int maxAlternates) { // record parameters _recognizer = recognizer; _maxAlternates = maxAlternates; try { _sapiRecoResult = recoResult as ISpRecoResult2; } catch (COMException) { _sapiRecoResult = null; } GCHandle gc = GCHandle.Alloc(sapiResultBlob, GCHandleType.Pinned); try { IntPtr buffer = gc.AddrOfPinnedObject(); int headerSize = Marshal.ReadInt32(buffer, 4); // Read header size directly from buffer - 4 is the offset of cbHeaderSize. if (headerSize == Marshal.SizeOf <SPRESULTHEADER_Sapi51>()) // SAPI 5.1 size { SPRESULTHEADER_Sapi51 legacyHeader = Marshal.PtrToStructure <SPRESULTHEADER_Sapi51>(buffer); _header = new SPRESULTHEADER(legacyHeader); _isSapi53Header = false; } else { _header = Marshal.PtrToStructure <SPRESULTHEADER>(buffer); _isSapi53Header = true; } // Validate the header fields _header.Validate(); // initialize the parent to be this result - this is needed for the homophones IntPtr phraseBuffer = new((long)buffer + (int)_header.ulPhraseOffset); SPSERIALIZEDPHRASE serializedPhrase = RecognizedPhrase.GetPhraseHeader(phraseBuffer, _header.ulPhraseDataSize, _isSapi53Header); // Get the alphabet of the main phrase, which should be the same as the current alphabet selected by us (applications). bool hasIPAPronunciation = (_header.fAlphabet & (uint)SPRESULTALPHABET.SPRA_APP_UPS) != 0; InitializeFromSerializedBuffer(this, serializedPhrase, phraseBuffer, (int)_header.ulPhraseDataSize, _isSapi53Header, hasIPAPronunciation); if (recoResult != null) { ExtractDictationAlternates(recoResult, maxAlternates); // Since we took ownership of this unmanaged object we can discard information that don't need. recoResult.Discard(SapiConstants.SPDF_ALL); } } finally { gc.Free(); } // save the sapi blobs splitting it in the relevant bits // audio _sapiAudioBlob = new byte[(int)_header.ulRetainedDataSize]; Array.Copy(sapiResultBlob, (int)_header.ulRetainedOffset, _sapiAudioBlob, 0, (int)_header.ulRetainedDataSize); // alternates _sapiAlternatesBlob = new byte[(int)_header.ulPhraseAltDataSize]; Array.Copy(sapiResultBlob, (int)_header.ulPhraseAltOffset, _sapiAlternatesBlob, 0, (int)_header.ulPhraseAltDataSize); }