Merge pull request #2074 from mozilla/bindings-idiomatic

Some bindings clean-up
This commit is contained in:
Reuben Morais 2019-04-25 13:20:50 +00:00 committed by GitHub
commit 656ab5734a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 108 additions and 107 deletions

View File

@ -100,7 +100,7 @@ After following the above build and installation instructions, the Node.JS bindi
``` ```
cd native_client/javascript cd native_client/javascript
make package make build
make npm-pack make npm-pack
``` ```

View File

@ -1,5 +1,4 @@
#!/usr/bin/env node #!/usr/bin/env node
'use strict'; 'use strict';
const Fs = require('fs'); const Fs = require('fs');
@ -69,6 +68,7 @@ function metadataToString(metadata) {
for (var i = 0; i < metadata.num_items; ++i) { for (var i = 0; i < metadata.num_items; ++i) {
retval += metadata.items[i].character; retval += metadata.items[i].character;
} }
Ds.FreeMetadata(metadata);
return retval; return retval;
} }
@ -135,5 +135,6 @@ audioStream.on('finish', () => {
} }
const inference_stop = process.hrtime(inference_start); const inference_stop = process.hrtime(inference_start);
console.error('Inference took %ds for %ds audio file.', totalTime(inference_stop), audioLength.toPrecision(4)); console.error('Inference took %ds for %ds audio file.', totalTime(inference_stop), audioLength.toPrecision(4));
Ds.DestroyModel(model);
process.exit(0); process.exit(0);
}); });

View File

@ -28,7 +28,6 @@ using namespace node;
// make sure the string returned by SpeechToText is freed // make sure the string returned by SpeechToText is freed
%typemap(newfree) char* "DS_FreeString($1);"; %typemap(newfree) char* "DS_FreeString($1);";
%typemap(newfree) Metadata* "DS_FreeMetadata($1);";
%newobject DS_SpeechToText; %newobject DS_SpeechToText;
%newobject DS_IntermediateDecode; %newobject DS_IntermediateDecode;
@ -61,19 +60,8 @@ using namespace node;
%append_output(SWIG_NewPointerObj(%as_voidptr(*$1), $*1_descriptor, 0)); %append_output(SWIG_NewPointerObj(%as_voidptr(*$1), $*1_descriptor, 0));
} }
// extend ModelState with a destructor so that DestroyModel will be called
// when the JavaScript object gets finalized.
%nodefaultctor ModelState; %nodefaultctor ModelState;
%nodefaultdtor ModelState; %nodefaultdtor ModelState;
struct ModelState {};
%extend ModelState {
~ModelState() {
DS_DestroyModel($self);
}
}
%nodefaultdtor Metadata; %nodefaultdtor Metadata;
%nodefaultctor Metadata; %nodefaultctor Metadata;
%nodefaultctor MetadataItem; %nodefaultctor MetadataItem;
@ -94,9 +82,6 @@ struct ModelState {};
v8::Handle<v8::Value> result = SWIGV8_ARRAY_NEW(); v8::Handle<v8::Value> result = SWIGV8_ARRAY_NEW();
return result; return result;
} }
~Metadata() {
DS_FreeMetadata($self);
}
} }
%rename ("%(strip:[DS_])s") ""; %rename ("%(strip:[DS_])s") "";

View File

@ -75,7 +75,13 @@ Model.prototype.finishStreamWithMetadata = function() {
return binding.FinishStreamWithMetadata.apply(null, arguments); return binding.FinishStreamWithMetadata.apply(null, arguments);
} }
function DestroyModel(model) {
return binding.DestroyModel(model._impl);
}
module.exports = { module.exports = {
Model: Model, Model: Model,
printVersions: binding.PrintVersions printVersions: binding.PrintVersions,
DestroyModel: DestroyModel,
FreeMetadata: binding.FreeMetadata
}; };

View File

@ -39,6 +39,7 @@ N_FEATURES = 26
# Size of the context window used for producing timesteps in the input vector # Size of the context window used for producing timesteps in the input vector
N_CONTEXT = 9 N_CONTEXT = 9
def convert_samplerate(audio_path): def convert_samplerate(audio_path):
sox_cmd = 'sox {} --type raw --bits 16 --channels 1 --rate 16000 --encoding signed-integer --endian little --compression 0.0 --no-dither - '.format(quote(audio_path)) sox_cmd = 'sox {} --type raw --bits 16 --channels 1 --rate 16000 --encoding signed-integer --endian little --compression 0.0 --no-dither - '.format(quote(audio_path))
try: try:
@ -50,11 +51,9 @@ def convert_samplerate(audio_path):
return 16000, np.frombuffer(output, np.int16) return 16000, np.frombuffer(output, np.int16)
def metadata_to_string(metadata): def metadata_to_string(metadata):
retval = '' return ''.join(item.character for item in metadata.items)
for item in range(metadata.num_items):
retval += metadata.items[item].character
return retval
class VersionAction(argparse.Action): class VersionAction(argparse.Action):
@ -65,6 +64,7 @@ class VersionAction(argparse.Action):
printVersions() printVersions()
exit(0) exit(0)
def main(): def main():
parser = argparse.ArgumentParser(description='Running DeepSpeech inference.') parser = argparse.ArgumentParser(description='Running DeepSpeech inference.')
parser.add_argument('--model', required=True, parser.add_argument('--model', required=True,

View File

@ -33,17 +33,19 @@ import_array();
%append_output(SWIG_NewPointerObj(%as_voidptr(*$1), $*1_descriptor, 0)); %append_output(SWIG_NewPointerObj(%as_voidptr(*$1), $*1_descriptor, 0));
} }
%extend struct MetadataItem {
MetadataItem* __getitem__(size_t i) {
return &$self[i];
}
}
%typemap(out) Metadata* { %typemap(out) Metadata* {
// owned, extended destructor needs to be called by SWIG // owned, extended destructor needs to be called by SWIG
%append_output(SWIG_NewPointerObj(%as_voidptr($1), $1_descriptor, SWIG_POINTER_OWN)); %append_output(SWIG_NewPointerObj(%as_voidptr($1), $1_descriptor, SWIG_POINTER_OWN));
} }
%typemap(out) MetadataItem* %{
$result = PyList_New(arg1->num_items);
for (int i = 0; i < arg1->num_items; ++i) {
PyObject* o = SWIG_NewPointerObj(SWIG_as_voidptr(&arg1->items[i]), SWIGTYPE_p_MetadataItem, 0);
PyList_SetItem($result, i, o);
}
%}
%extend struct Metadata { %extend struct Metadata {
~Metadata() { ~Metadata() {
DS_FreeMetadata($self); DS_FreeMetadata($self);

View File

@ -1,6 +1,5 @@
[build_ext] [build_ext]
include-dirs=./ include-dirs=./
swig-opts=-c++ -keyword
build-lib=temp_build build-lib=temp_build
build-temp=temp_build build-temp=temp_build

View File

@ -7,6 +7,7 @@ import os
import subprocess import subprocess
import sys import sys
def main():
try: try:
import numpy import numpy
try: try:
@ -47,6 +48,8 @@ def lib_dirs_split(a):
if os.name == 'nt': if os.name == 'nt':
return [] return []
raise AssertionError('os.name == java not expected')
def libs_split(a): def libs_split(a):
if os.name == 'posix': if os.name == 'posix':
return a.split('-l')[1:] return a.split('-l')[1:]
@ -54,12 +57,14 @@ def libs_split(a):
if os.name == 'nt': if os.name == 'nt':
return a.split('.lib')[0:1] return a.split('.lib')[0:1]
ds_ext = Extension('deepspeech._impl', raise AssertionError('os.name == java not expected')
['impl.i'],
ds_ext = Extension(name='deepspeech._impl',
sources=['impl.i'],
include_dirs=[numpy_include, '../'], include_dirs=[numpy_include, '../'],
library_dirs=list(map(lambda x: x.strip(), lib_dirs_split(os.getenv('MODEL_LDFLAGS', '')))), library_dirs=list(map(lambda x: x.strip(), lib_dirs_split(os.getenv('MODEL_LDFLAGS', '')))),
libraries = list(map(lambda x: x.strip(), libs_split(os.getenv('MODEL_LIBS', '')))) libraries=list(map(lambda x: x.strip(), libs_split(os.getenv('MODEL_LIBS', '')))),
) swig_opts=['-c++', '-keyword', '-builtin'])
setup(name=project_name, setup(name=project_name,
description='A library for running inference on a DeepSpeech model', description='A library for running inference on a DeepSpeech model',
@ -97,3 +102,6 @@ setup(name = project_name,
'Topic :: Scientific/Engineering', 'Topic :: Scientific/Engineering',
'Topic :: Utilities', 'Topic :: Utilities',
]) ])
if __name__ == '__main__':
main()