Skip to content

Commit e123ec3

Browse files
committed
[BTRemoteControl] Facilitate AI with audio buffering
1 parent 093d067 commit e123ec3

File tree

5 files changed

+303
-10
lines changed

5 files changed

+303
-10
lines changed

BluetoothRemoteControl/BluetoothRemoteControl.conf.in

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ configuration.add("codec", "pcm")
1010
configuration.add("samplerate", "16000")
1111
configuration.add("channels", "1")
1212
configuration.add("resolution", "16")
13-
configuration.add("configuration", "None")
13+
configuration.add("configuration", None)
1414
configuration.add("serviceuuid", "f0e0d000-a000-b000-c000-987654321000")
1515
configuration.add("commanduuid", "f0e0d001-a000-b000-c000-987654321000")
1616
configuration.add("datauuid", "f0e0d002-a000-b000-c000-987654321000")
17+
configuration.add("audiobuffersize", 0)
18+
configuration.add("firstaudiochunksize", 100)
19+
configuration.add("audiochunksize", 100)

BluetoothRemoteControl/BluetoothRemoteControl.cpp

Lines changed: 116 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,14 @@ namespace Plugin {
204204
_voiceHandler = nullptr;
205205
}
206206

207+
if (_buffer != nullptr) {
208+
delete _buffer;
209+
_buffer = nullptr;
210+
}
211+
207212
_service->Release();
208213
_service = nullptr;
214+
209215
}
210216
}
211217

@@ -437,6 +443,56 @@ namespace Plugin {
437443

438444
_gattRemote->Decoder(_configLine);
439445

446+
if (_buffer != nullptr) {
447+
delete _buffer;
448+
_buffer = nullptr;
449+
}
450+
451+
Config config;
452+
config.FromString(_configLine);
453+
454+
Exchange::IVoiceProducer::IProfile* profile = _gattRemote->SelectedProfile();
455+
ASSERT(profile != nullptr);
456+
457+
const uint16_t maxChunkDuration = std::max(config.AudioChunkSize.Value(), config.FirstAudioChunkSize.Value());
458+
459+
if (maxChunkDuration != 0) {
460+
// If buffer size is not specified, then set it based on the configured chunk sizes
461+
const uint32_t maxDuration = std::max(config.AudioBufferSize.Value(), (maxChunkDuration + config.AudioChunkSize.Value()));
462+
const uint32_t bufferSize = TimeToBytes(maxDuration, profile);
463+
_firstAudioChunkSize = TimeToBytes(config.FirstAudioChunkSize.Value(), profile);
464+
_audioChunkSize = TimeToBytes(config.AudioChunkSize.Value(), profile);
465+
466+
// Some sanity...
467+
ASSERT(bufferSize <= (512 * 1024));
468+
ASSERT(_firstAudioChunkSize <= (512 * 1024));
469+
ASSERT(_audioChunkSize <= (512 * 1024));
470+
471+
_buffer = new RingBufferType<uint32_t>(bufferSize);
472+
ASSERT(_buffer != nullptr);
473+
474+
TRACE(Trace::Information, (_T("Audio buffer size is %d bytes (%d ms)"), bufferSize, maxDuration));
475+
476+
if (_firstAudioChunkSize != 0) {
477+
TRACE(Trace::Information, (_T("First audio chunk size is %d bytes (%d ms)"), _firstAudioChunkSize, config.FirstAudioChunkSize.Value()));
478+
}
479+
else {
480+
TRACE(Trace::Information, (_T("Audio will not be pre-buffered")));
481+
}
482+
483+
if (_audioChunkSize != 0) {
484+
TRACE(Trace::Information, (_T("Audio chunk size is %d bytes (%d ms)"), _audioChunkSize, config.AudioChunkSize.Value()));
485+
}
486+
else {
487+
TRACE(Trace::Information, (_T("Audio chunks will not be buffered")));
488+
}
489+
}
490+
else {
491+
TRACE(Trace::Information, (_T("Audio buffering is disabled")));
492+
}
493+
494+
profile->Release();
495+
440496
// Store the settings, if not already done..
441497
Core::File settingsFile(_service->PersistentPath() + _gattRemote->Address() + _T(".json"));
442498
if ( (settingsFile.Exists() == false) && (settingsFile.Create() == true) ) {
@@ -458,6 +514,12 @@ namespace Plugin {
458514

459515
_adminLock.Lock();
460516

517+
_sequence = 0;
518+
519+
if (_buffer != nullptr) {
520+
_buffer->Reset();
521+
}
522+
461523
if (_voiceHandler != nullptr) {
462524
_voiceHandler->Start(profile);
463525
}
@@ -494,6 +556,11 @@ namespace Plugin {
494556

495557
_adminLock.Lock();
496558

559+
if ((_buffer != nullptr) && (_sequence != 0)) {
560+
// Push out whatever is left (but only if a complete first chunk went out)
561+
SendOut(_buffer->Used());
562+
}
563+
497564
if (_voiceHandler != nullptr) {
498565
_voiceHandler->Stop();
499566
}
@@ -507,7 +574,6 @@ namespace Plugin {
507574
_recorder.Close();
508575
}
509576

510-
511577
TRACE(Trace::Information, (_T("Audio transmission: end")));
512578
}
513579
}
@@ -516,19 +582,64 @@ namespace Plugin {
516582
{
517583
_adminLock.Lock();
518584

585+
const uint32_t chunkSize = ((_firstAudioChunkSize != 0) && (_sequence == 0)? _firstAudioChunkSize : _audioChunkSize);
586+
587+
if (chunkSize != 0) {
588+
ASSERT(_buffer != nullptr);
589+
590+
if (_buffer->Free() < length) {
591+
const uint32_t newSize = std::max((_buffer->Capacity() * 2), (_buffer->Capacity() + length));
592+
TRACE(Trace::Warning, (_T("Ring buffer size is too small, resizing from %d to %d bytes!"), _buffer->Capacity(), newSize));
593+
_buffer->Resize(newSize);
594+
}
595+
596+
const uint32_t written = _buffer->Push(length, dataBuffer);
597+
DEBUG_VARIABLE(written);
598+
ASSERT(written == length);
599+
600+
while (_buffer->Used() >= chunkSize) {
601+
SendOut(chunkSize);
602+
}
603+
}
604+
else if (length > 0) {
605+
SendOut(seq, length, dataBuffer);
606+
}
607+
608+
if (_recorder.IsOpen() == true) {
609+
_recorder.Write(length, dataBuffer);
610+
}
611+
612+
_adminLock.Unlock();
613+
}
614+
615+
void BluetoothRemoteControl::SendOut(const uint32_t seq, const uint32_t length, const uint8_t dataBuffer[])
616+
{
617+
ASSERT(length != 0);
618+
ASSERT(dataBuffer != nullptr);
619+
519620
if (_voiceHandler != nullptr) {
520621
_voiceHandler->Data(seq, dataBuffer, length);
521622
}
522623
else {
523624
string frame;
524625
Core::ToString(dataBuffer, length, true, frame);
525-
event_audioframe(seq, frame);
626+
event_audioframe(seq, length, frame);
526627
}
628+
}
527629

528-
_adminLock.Unlock();
630+
void BluetoothRemoteControl::SendOut(const uint32_t length)
631+
{
632+
if (length != 0) {
633+
uint8_t* buffer = static_cast<uint8_t*>(ALLOCA(length));
634+
const uint32_t read = _buffer->Pop(length, buffer);
529635

530-
if (_recorder.IsOpen() == true) {
531-
_recorder.Write(length, dataBuffer);
636+
if (read > 0) {
637+
SendOut(_sequence, read, buffer);
638+
_sequence++;
639+
}
640+
else if (read < length) {
641+
ASSERT(!"not enouqh data");
642+
}
532643
}
533644
}
534645

0 commit comments

Comments
 (0)