-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDeepSpeechC.cpp
More file actions
156 lines (137 loc) · 4.53 KB
/
Copy pathDeepSpeechC.cpp
File metadata and controls
156 lines (137 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <QtDebug>
#include <QFile>
#include <QDir>
#include <QStandardPaths>
#include <thread>
#include "DeepSpeechC.h"
#include "Game.h"
//Convenience function to debug file path issues
void listFiles(QString dir)
{
QDir d(dir);
QStringList list = d.entryList();
qInfo()<<"Listing files in "<<dir;
for( int i = 0; i< list.size(); ++i)
{
qInfo()<<list[i];
}
}
DeepSpeech::DeepSpeech(QObject *parent) : QObject(parent)
{
}
void DeepSpeech::init()
{
#ifdef Q_OS_ANDROID
//Copy model file from apk to accessible location
QFile dfile("assets:/models/ds93.tflite");
QString filePath = QStandardPaths::writableLocation( QStandardPaths::StandardLocation::AppLocalDataLocation );
qInfo()<<"Data write location"<<filePath;
filePath.append( "/ds93.tflite");
if (dfile.exists()) { //If model file exists
qInfo()<<"Model file exists @"<<dfile.fileName();
if(!QFile::exists( filePath ) )
{//Check if it exists in this location already
qInfo()<<"Model files does not exist at "<<filePath;
if( dfile.copy( filePath ) )
{//Copy over if it doesnt
qInfo()<<"Copying model to : "<<filePath;
QFile::setPermissions( filePath, QFile::WriteOwner | QFile::ReadOwner );
}
}
}
#else //For Windows/Mac/Linux
QString filePath("./models/ds93.pbmm");
#endif
std::string modelPath = filePath.toStdString();
int result = 0;
result = DS_CreateModel(modelPath.c_str(), &model);
qInfo()<<"Creating DS Model : "<<result<<" on thread "<<this->thread();
int idealSample = 0;
idealSample = DS_GetModelSampleRate(model);
qInfo()<<"Ideal Sample Rate : "<<idealSample;
QAudioFormat recFormat;
recFormat.setSampleRate(idealSample);
recFormat.setByteOrder(QAudioFormat::LittleEndian);
recFormat.setChannelCount(1);
recFormat.setSampleSize(16);
recFormat.setCodec("audio/pcm");
recFormat.setSampleType(QAudioFormat::SignedInt);
recorder = new QAudioInput (recFormat);
QIODevice* device = recorder->start();
qInfo()<<"Started recording audio on "<<device;
QObject::connect(device, &QIODevice::readyRead, this, &DeepSpeech::transcribeAudio, Qt::QueuedConnection );
}
DeepSpeech::~DeepSpeech()
{
if(recorder)
{
delete recorder;
recorder = nullptr;
}
}
void DeepSpeech::startRecording()
{
qInfo()<<"Recording";
std::lock_guard<std::mutex> guard(lock);
if(recorder->state() == QAudio::State::SuspendedState)
{
recorder->resume();
}
qInfo()<<"Recorder state now is "<<recorder->state();
int ret = DS_CreateStream(model, &state);
qInfo()<<"Setting up Model Stream : "<<ret;
}
void DeepSpeech::stopRecording()
{
qInfo()<<"Stopping Recording";
std::lock_guard<std::mutex> guard(lock);
//recorder->suspend();
qInfo()<<"Recorder state now is "<<recorder->state();
qInfo()<<"Clearing Hotwords and Freeing stream"<<this->thread();
DS_ClearHotWords(model);
if(state)
{
DS_FreeStream(state);
}
state = nullptr;
}
void DeepSpeech::setHotword(QString hotword)
{
std::string word = hotword.toStdString();
DS_AddHotWord(model, word.c_str(), 5.0f );
}
void DeepSpeech::transcribeAudio()
{
try {
//qInfo()<<"Buffer size "<<recorder->bufferSize();
std::lock_guard<std::mutex> guard(lock);
qInfo()<<"Bytes ready"<<recorder->bytesReady();
QIODevice* device = static_cast<QIODevice*>(sender());
if(state)
{
QByteArray data = device->readAll();
qInfo()<<"Received audio bytes "<<data.size();
if(data.size() > 50000)
{//Optimisation for phones or slow hardware, skip these bytes to prevent snowballing buffer size
return;
}
DS_FeedAudioContent(state, reinterpret_cast<const short*>(data.data()), data.size()/2);
// qInfo()<<"Transcribed "<<data.size()<<" bytes...";
// qInfo()<<"Transcribing on thread "<<this->thread();
samplesCollected += data.size()/2;
if(samplesCollected > 16000)
{
std::string qtext;
char* text = DS_IntermediateDecode(state);
qInfo()<<text;
qtext = text;
DS_FreeString(text);
//Inform Game of new speech by user
emit transcript(QString::fromStdString(qtext));
samplesCollected = 0;
}
}
} catch (std::exception& e) {
qInfo()<<e.what();
}
}