Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ out/
toolchain
say
/wip

# Nintendo DS
.DS_Store
16 changes: 16 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cStandard": "c17",
"cppStandard": "c++14",
"intelliSenseMode": "macos-clang-arm64"
}
],
"version": 4
}
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{
"type": "lldb",
"request": "launch",
"name": "DECtalk for NodeJS",
"preLaunchTask": "npm: build:dev - node",
"program": "/usr/bin/env",
"args": [
"node",
"${workspaceFolder}/node/src/index.js"
]
}]
}
2 changes: 2 additions & 0 deletions node/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
build/
35 changes: 35 additions & 0 deletions node/binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"targets": [
{
"target_name": "dectalk",
"cflags!": [ "-fno-exceptions" ],
"cflags_cc!": [ "-fno-exceptions" ],
"sources": [
"src/dectalk.cc",
"<!@(node -p \"require('fs').readdirSync('../src').map(f=>'../src/'+f).join(' ')\")"
],
"include_dirs": [
"../include",
"<!@(node -p \"require('node-addon-api').include\")"
],
'defines': [
'NAPI_DISABLE_CPP_EXCEPTIONS',
'NO_FILESYSTEM',
'_REENTRANT',
'NOMME',
'LTSSIM',
'TTSSIM',
'ANSI',
'BLD_DECTALK_DLL',
'ENGLISH',
'ENGLISH_US',
'ACCESS32',
'TYPING_MODE',
'ACNA',
'DISABLE_AUDIO',
'SINGLE_THREADED',
'__unix__'
],
}
]
}
50 changes: 50 additions & 0 deletions node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions node/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "hello_world",
"version": "0.0.0",
"description": "Node.js Addons Example #1",
"main": "src/index.js",
"private": true,
"dependencies": {
"bindings": "~1.5.0",
"node-addon-api": "^8.1.0"
},
"scripts": {
"build": "node-gyp build",
"build:dev": "node-gyp build --debug"
},
"gypfile": true,
"devDependencies": {
"node-api-headers": "^1.8.0"
}
}
57 changes: 57 additions & 0 deletions node/src/dectalk.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <napi.h>

extern "C" {
#include "epsonapi.h"
}

Napi::FunctionReference callback;
bool callbackWasSet = false;

short* audio_callback(short *data, long length, int phoneme) {
Napi::Env env = callback.Env();

Napi::Buffer<short> array = Napi::Buffer<short>::New(env, data, length);

callback.Call({ array });
}

Napi::Value setCallback(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();

callback = Napi::Persistent(info[0].As<Napi::Function>());
callbackWasSet = true;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops still havent done anything with this lol


return Napi::String::New(env, "Done");
}

Napi::Value say(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();

Napi::String text = info[0].As<Napi::String>();
Napi::Number format = info[1].As<Napi::Number>();

const std::string cppstr = text.ToString().Utf8Value();
const char* input = cppstr.c_str();
const int fmt = format.Int32Value();

int result = TextToSpeechStart((char*) input, NULL, fmt);

if (result == 0) TextToSpeechSync();

return Napi::Number::New(env, result);
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "setCallback"),
Napi::Function::New(env, setCallback));

exports.Set(Napi::String::New(env, "say"),
Napi::Function::New(env, say));

TextToSpeechInit(audio_callback, NULL);

return exports;
}

// Register and initialize native add-on
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
4 changes: 4 additions & 0 deletions node/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface ILibDectalk {
setCallback: (callback: (buffer: Buffer) => void) => void;
say: (text: string, mode: 0 | 1) => number;
}
56 changes: 56 additions & 0 deletions node/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import bindings from "bindings";
import fs from "node:fs"

/** @type {ILibDectalk} */
const libdectalk = bindings("dectalk");

const toBytes = (number) => {
return [0xff & number,
0xff & (number >> 8),
0xff & (number >> 16),
0xff & (number >> 24)]
}

/** @type {(text: string) => Promise<Buffer>} */
const say = (text) => {
const format = 1;
const audioBuffer = [];
let dataLength = 0;

/** @type {(chunkData: Buffer) => void} */
const callback = (chunkData) => {
// copy the buffer immediately before its destroyed
audioBuffer.push(Buffer.from(chunkData));
dataLength += chunkData.byteLength;
}

libdectalk.setCallback(callback)
libdectalk.say(text, format);

const sampleRate = format ? 11025 : 8000
const bufferLength = 44 + dataLength;

// Generate a WAV header
const header = Buffer.from([
0x52, 0x49, 0x46, 0x46, // RIFF
...toBytes(bufferLength), // WAV size
0x57, 0x41, 0x56, 0x45, // WAVE
0x66, 0x6d, 0x74, 0x20, // fmt
0x10, 0x00, 0x00, 0x00, // fmt chunk size
0x01, 0x00, 0x01, 0x00, // Audio format 1=PCM & Number of channels 1=Mono
...toBytes(sampleRate), // Sampling Frequency in Hz
...toBytes(sampleRate * 2), // bytes per second
0x02, 0x00, 0x10, 0x00, // 2=16-bit mono & Number of bits per sample
0x64, 0x61, 0x74, 0x61, // data
...toBytes(dataLength) // data size
])

return Buffer.concat([header, ...audioBuffer])
}

const buffer = say("This is a message from Node J S");
fs.writeFileSync("first.wav", buffer);

const buffer2 = say("This is a second message from Node J S");
fs.writeFileSync("second.wav", buffer2);
console.log("end of programme");
2 changes: 1 addition & 1 deletion wasm/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ EM_JS(void, js_audio_callback, (short* data, int length, int phoneme, int buffer
});

EMSCRIPTEN_KEEPALIVE
short* audio_callback(short *data, long length) {
short* audio_callback(short *data, long length, int phoneme) {
// Get current phoneme and pass it to JavaScript along with audio data
int current_phoneme = last_phoneme & 0x00FF;

Expand Down
Loading