Skip to content

Instantly share code, notes, and snippets.

@willwade
Created November 30, 2024 18:57
Show Gist options
  • Save willwade/478e0cf731b642a09986f4f10cec1e07 to your computer and use it in GitHub Desktop.
Save willwade/478e0cf731b642a09986f4f10cec1e07 to your computer and use it in GitHub Desktop.

Idea is to bridge to 32 bit stuff with 64 bit python

Compile the DLL

1.	Use a 32-bit version of Visual Studio to compile the code as a 32-bit DLL.
2.	Set the project to build a DLL:
•	Open Project Properties > Configuration Properties > General.
•	Set Configuration Type to Dynamic Library (.dll).
3.	Specify the output architecture:
•	Under Configuration Properties > Linker > Advanced, set Target Machine to MachineX86 for 32-bit.
#include <windows.h>
#include <sapi.h> // Include SAPI header
#include <string>
extern "C" __declspec(dllexport) int GetSAPI4Voices(char* buffer, int bufferSize) {
ISpVoice* pVoice = nullptr;
if (FAILED(CoInitialize(nullptr))) {
return -1; // Failed to initialize COM
}
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
if (FAILED(hr)) {
CoUninitialize();
return -2; // Failed to create SAPI voice instance
}
// Enumerate voices
IEnumSpObjectTokens* pVoiceTokens = nullptr;
SpEnumTokens(SPCAT_VOICES, NULL, NULL, &pVoiceTokens);
ULONG voiceCount;
pVoiceTokens->GetCount(&voiceCount);
std::string voiceList;
for (ULONG i = 0; i < voiceCount; i++) {
ISpObjectToken* pToken = nullptr;
if (SUCCEEDED(pVoiceTokens->Item(i, &pToken))) {
WCHAR* name = nullptr;
pToken->GetStringValue(NULL, &name);
voiceList += std::string(_bstr_t(name)) + "\n"; // Convert WCHAR* to std::string
pToken->Release();
}
}
pVoiceTokens->Release();
pVoice->Release();
CoUninitialize();
// Copy to buffer
if (voiceList.size() < bufferSize) {
strcpy(buffer, voiceList.c_str());
return 0; // Success
}
return -3; // Buffer too small
}
extern "C" __declspec(dllexport) int SynthesizeSAPI4Text(const char* text) {
ISpVoice* pVoice = nullptr;
if (FAILED(CoInitialize(nullptr))) {
return -1; // Failed to initialize COM
}
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
if (FAILED(hr)) {
CoUninitialize();
return -2; // Failed to create SAPI voice instance
}
// Convert text to WCHAR
std::wstring wtext = std::wstring(text, text + strlen(text));
hr = pVoice->Speak(wtext.c_str(), SPF_DEFAULT, NULL);
pVoice->Release();
CoUninitialize();
return SUCCEEDED(hr) ? 0 : -3; // Return success or error code
}
import ctypes
# Load the DLL (ensure it's in the same directory or specify the full path)
sapi4_bridge = ctypes.WinDLL("path/to/sapi4_bridge.dll")
# Define the buffer size
BUFFER_SIZE = 1024
buffer = ctypes.create_string_buffer(BUFFER_SIZE)
# Call GetSAPI4Voices
result = sapi4_bridge.GetSAPI4Voices(buffer, BUFFER_SIZE)
if result == 0:
print("SAPI 4 Voices:")
print(buffer.value.decode("utf-8"))
else:
print(f"Error retrieving voices: {result}")
# Call SynthesizeSAPI4Text
text = "Hello from SAPI 4!"
result = sapi4_bridge.SynthesizeSAPI4Text(text.encode("utf-8"))
if result == 0:
print("Text synthesized successfully!")
else:
print(f"Error synthesizing text: {result}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment