opensllayer.cpp 22.6 KB
Newer Older
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
/*
 *  Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
 */

Tristan Matthews's avatar
Tristan Matthews committed
31
32
#include <cstdio>
#include <cassert>
Adrien Béraud's avatar
Adrien Béraud committed
33
#include <unistd.h>
34

35
#include "logger.h"
36
#include "array_size.h"
37
#include "manager.h"
38
#include "mainbuffer.h"
39

40
41
#include "opensllayer.h"

42
43
44
const int OpenSLLayer::NB_BUFFER_PLAYBACK_QUEUE = ANDROID_BUFFER_QUEUE_LENGTH;
const int OpenSLLayer::NB_BUFFER_CAPTURE_QUEUE = ANDROID_BUFFER_QUEUE_LENGTH;

45
static long sawPtr = 0;
46
47
static void generateSawTooth(short *buffer, int length)
{
Adrien Béraud's avatar
Adrien Béraud committed
48
    assert(nullptr != buffer);
49
50
51
    assert(length > 0);

    unsigned int i;
52

53
    for (i = 0; i < length; ++i, ++sawPtr) {
54
        buffer[i] = 32768 - ((sawPtr % 10) * 6600);
55
56
57
    }
}

58
class OpenSLThread {
59
60
    public:
        OpenSLThread(OpenSLLayer *opensl);
61
        ~OpenSLThread();
62
        void initAudioLayer();
63
64
        void start();
        bool isRunning() const;
65
66

    private:
67
68
69
        void run();
        static void *runCallback(void *context);

70
        NON_COPYABLE(OpenSLThread);
71
        pthread_t thread_;
72
        OpenSLLayer* opensl_;
73
        bool running_;
74
75
76
};

OpenSLThread::OpenSLThread(OpenSLLayer *opensl)
77
    : thread_(0), opensl_(opensl), running_(false)
78
{}
79

80
OpenSLThread::~OpenSLThread()
81
{
82
    running_ = false;
83
84
    opensl_->shutdownAudioEngine();

85
    if (thread_)
Adrien Béraud's avatar
Adrien Béraud committed
86
        pthread_join(thread_, nullptr);
87
88
}

Tristan Matthews's avatar
Tristan Matthews committed
89
90
void
OpenSLThread::start()
91
92
{
    running_ = true;
Adrien Béraud's avatar
Adrien Béraud committed
93
    pthread_create(&thread_, nullptr, &runCallback, this);
94
95
96
97
98
99
100
}

void *
OpenSLThread::runCallback(void *data)
{
    OpenSLThread *context = static_cast<OpenSLThread*>(data);
    context->run();
Adrien Béraud's avatar
Adrien Béraud committed
101
    return nullptr;
102
103
}

Tristan Matthews's avatar
Tristan Matthews committed
104
105
bool
OpenSLThread::isRunning() const
106
107
{
    return running_;
108
109
}

Tristan Matthews's avatar
Tristan Matthews committed
110
111
void
OpenSLThread::initAudioLayer()
112
113
114
{
    opensl_->initAudioEngine();
    opensl_->initAudioPlayback();
115
    opensl_->initAudioCapture();
116
117
118
119
120
}

/**
 * Reimplementation of run()
 */
Tristan Matthews's avatar
Tristan Matthews committed
121
122
void
OpenSLThread::run()
123
124
125
126
{
    initAudioLayer();

    opensl_->startAudioPlayback();
127
    opensl_->startAudioCapture();
128

129
130
    while (opensl_->isStarted_)
        usleep(20000); // 20 ms
131
132
133
134
135
136
137
}

// Constructor
OpenSLLayer::OpenSLLayer()
    : indexIn_(0)
    , indexOut_(0)
    , indexRing_(0)
138
    , audioThread_(0)
139
    , isStarted_(false)
140
141
142
143
144
145
146
147
148
149
150
    , engineObject_(0)
    , engineInterface_(0)
    , outputMixer_(0)
    , playerObject_(0)
    , recorderObject_(0)
    , playerInterface_(0)
    , recorderInterface_(0)
    , playbackBufferQueue_(0)
    , recorderBufferQueue_(0)
    , playbackBufferIndex_(0)
    , recordBufferIndex_(0)
151
152
    , playbackBufferStack_(ANDROID_BUFFER_QUEUE_LENGTH, AudioBuffer(BUFFER_SIZE))
    , recordBufferStack_(ANDROID_BUFFER_QUEUE_LENGTH, AudioBuffer(BUFFER_SIZE))
153
154
155
156
157
158
{
}

// Destructor
OpenSLLayer::~OpenSLLayer()
{
Alexandre Savard's avatar
Alexandre Savard committed
159
    stopStream();
160
161
}

Adrien Béraud's avatar
Adrien Béraud committed
162
163
#define RECORD_AUDIO_TODISK

164
165
#ifdef RECORD_AUDIO_TODISK
#include <fstream>
166
std::ofstream opensl_outfile;
167
std::ofstream opensl_infile;
168
169
#endif

170
171
172
void
OpenSLLayer::startStream()
{
173
    if (isStarted_)
174
175
        return;

176
177
    DEBUG("Start OpenSL audio layer");

Adrien Béraud's avatar
Adrien Béraud committed
178
    if (audioThread_ == nullptr) {
179
#ifdef RECORD_AUDIO_TODISK
180
181
        opensl_outfile.open("/data/data/com.savoirfairelinux.sflphone/opensl_playback.raw", std::ofstream::out | std::ofstream::binary);
        opensl_infile.open("/data/data/com.savoirfairelinux.sflphone/opensl_record.raw", std::ofstream::out | std::ofstream::binary);
182
183
#endif

184
        audioThread_ = new OpenSLThread(this);
185
        isStarted_ = true;
186
187
        audioThread_->start();
    }
188

189
190
191
192
193
}

void
OpenSLLayer::stopStream()
{
194
    if (not isStarted_)
195
196
        return;

197
198
199
200
201
    DEBUG("Stop OpenSL audio layer");

    stopAudioPlayback();
    stopAudioCapture();

202
203
204
    isStarted_ = false;

    delete audioThread_;
Adrien Béraud's avatar
Adrien Béraud committed
205
    audioThread_ = nullptr;
206
#ifdef RECORD_AUDIO_TODISK
207
    opensl_outfile.close();
208
    opensl_infile.close();
209
#endif
210
211
212
213
214
215
216
}

void
OpenSLLayer::initAudioEngine()
{
    SLresult result;

217
    DEBUG("Create Audio Engine\n");
Adrien Béraud's avatar
Adrien Béraud committed
218
    result = slCreateEngine(&engineObject_, 0, nullptr, 0, nullptr, nullptr);
219
220
    assert(SL_RESULT_SUCCESS == result);

221
    DEBUG("Realize Audio Engine\n");
222
    result = (*engineObject_)->Realize(engineObject_, SL_BOOLEAN_FALSE);
223
224
    assert(SL_RESULT_SUCCESS == result);

225
    DEBUG("Create Audio Engine Interface\n");
226
    result = (*engineObject_)->GetInterface(engineObject_, SL_IID_ENGINE, &engineInterface_);
227
228
    assert(SL_RESULT_SUCCESS == result);

229
    DEBUG("Create Output Mixer\n");
Adrien Béraud's avatar
Adrien Béraud committed
230
    result = (*engineInterface_)->CreateOutputMix(engineInterface_, &outputMixer_, 0, nullptr, nullptr);
231
232
    assert(SL_RESULT_SUCCESS == result);

233
    DEBUG("Realize Output Mixer\n");
234
    result = (*outputMixer_)->Realize(outputMixer_, SL_BOOLEAN_FALSE);
235
236
    assert(SL_RESULT_SUCCESS == result);

237
    DEBUG("Audio Engine Initialization Done\n");
238
239
}

240
void
241
242
OpenSLLayer::shutdownAudioEngine()
{
243

244
    // destroy buffer queue audio player object, and invalidate all associated interfaces
245
    DEBUG("Shutdown audio player\n");
246

Adrien Béraud's avatar
Adrien Béraud committed
247
    if (playerObject_ != nullptr) {
248
        (*playerObject_)->Destroy(playerObject_);
Adrien Béraud's avatar
Adrien Béraud committed
249
250
251
        playerObject_ = nullptr;
        playerInterface_ = nullptr;
        playbackBufferQueue_ = nullptr;
252
    }
253

254
    // destroy output mix object, and invalidate all associated interfaces
255
    DEBUG("Shutdown audio mixer\n");
256

Adrien Béraud's avatar
Adrien Béraud committed
257
    if (outputMixer_ != nullptr) {
258
        (*outputMixer_)->Destroy(outputMixer_);
Adrien Béraud's avatar
Adrien Béraud committed
259
        outputMixer_ = nullptr;
260
261
    }

Adrien Béraud's avatar
Adrien Béraud committed
262
	if(recorderObject_ != nullptr){
263
		(*recorderObject_)->Destroy(recorderObject_);
Adrien Béraud's avatar
Adrien Béraud committed
264
265
266
		recorderObject_ = nullptr;
		recorderInterface_ = nullptr;
		recorderBufferQueue_ = nullptr;
267
268
	}

269
    // destroy engine object, and invalidate all associated interfaces
270
    DEBUG("Shutdown audio engine\n");
Adrien Béraud's avatar
Adrien Béraud committed
271
    if (engineObject_ != nullptr) {
272
        (*engineObject_)->Destroy(engineObject_);
Adrien Béraud's avatar
Adrien Béraud committed
273
274
        engineObject_ = nullptr;
        engineInterface_ = nullptr;
275
    }
276
277
278
279
280
}

void
OpenSLLayer::initAudioPlayback()
{
Adrien Béraud's avatar
Adrien Béraud committed
281
282
283
    assert(nullptr != engineObject_);
    assert(nullptr != engineInterface_);
    assert(nullptr != outputMixer_);
284
285
286
287

    SLresult result;

    // Initialize the location of the buffer queue
288
    DEBUG("Create playback queue\n");
289
    SLDataLocator_AndroidSimpleBufferQueue bufferLocation = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
290
291
                                           NB_BUFFER_PLAYBACK_QUEUE
                                                            };
292
293

    // Initnialize the audio format for this queue
294
    DEBUG("Setting audio format\n");
295
    SLDataFormat_PCM audioFormat = {SL_DATAFORMAT_PCM, 1,
296
297
                                    SL_SAMPLINGRATE_8,
                                    SL_PCMSAMPLEFORMAT_FIXED_16,
298
299
300
301
                                    SL_PCMSAMPLEFORMAT_FIXED_16,
                                    SL_SPEAKER_FRONT_CENTER,
                                    SL_BYTEORDER_LITTLEENDIAN
                                   };
302
303

    // Create the audio source
304
    DEBUG("Set Audio Sources\n");
305
306
    SLDataSource audioSource = {&bufferLocation, &audioFormat};

307
    // Cofiguration fo the audio sink as an output mixer
308
    DEBUG("Set output mixer location\n");
309
    SLDataLocator_OutputMix mixerLocation = {SL_DATALOCATOR_OUTPUTMIX, outputMixer_};
Adrien Béraud's avatar
Adrien Béraud committed
310
    SLDataSink audioSink = {&mixerLocation, nullptr};
311

312
    const SLInterfaceID ids[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
313
314
                                 SL_IID_VOLUME, SL_IID_ANDROIDCONFIGURATION
                                };
315
    const SLboolean req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
316

317
    const unsigned nbInterface = ARRAYSIZE(ids);
318

319
    // create audio player
320
    DEBUG("Create audio player\n");
321
    result = (*engineInterface_)->CreateAudioPlayer(engineInterface_, &playerObject_, &audioSource, &audioSink, nbInterface, ids, req);
322
323
    assert(SL_RESULT_SUCCESS == result);

Tristan Matthews's avatar
Tristan Matthews committed
324
325
326
    SLAndroidConfigurationItf playerConfig;
    SLint32 streamType = SL_ANDROID_STREAM_VOICE;

327
    result = (*playerObject_)->GetInterface(playerObject_,
328
329
330
                                            SL_IID_ANDROIDCONFIGURATION,
                                            &playerConfig);

331
332
    if (result == SL_RESULT_SUCCESS && playerConfig) {
        result = (*playerConfig)->SetConfiguration(
333
334
                     playerConfig, SL_ANDROID_KEY_STREAM_TYPE,
                     &streamType, sizeof(SLint32));
335
    }
336

337
338
339
340
    if (result != SL_RESULT_SUCCESS) {
        ERROR("Unable to set android player configuration");
    }

341
    DEBUG("Realize audio player\n");
342
    result = (*playerObject_)->Realize(playerObject_, SL_BOOLEAN_FALSE);
343
344
345
    assert(SL_RESULT_SUCCESS == result);

    // create audio interface
346
    DEBUG("Create audio player interface\n");
347
    result = (*playerObject_)->GetInterface(playerObject_, SL_IID_PLAY, &playerInterface_);
348
349
350
    assert(SL_RESULT_SUCCESS == result);

    // create the buffer queue interface
351
    DEBUG("Create buffer queue interface\n");
352
    result = (*playerObject_)->GetInterface(playerObject_, SL_IID_BUFFERQUEUE, &playbackBufferQueue_);
353
354
355
    assert(SL_RESULT_SUCCESS == result);

    // register the buffer queue on the buffer object
356
    DEBUG("Register audio callback\n");
357
    result = (*playbackBufferQueue_)->RegisterCallback(playbackBufferQueue_, audioPlaybackCallback, this);
358
359
    assert(SL_RESULT_SUCCESS == result);

360
    DEBUG("Audio Playback Initialization Done\n");
361
362
363
364
365
366
367
368
}

void
OpenSLLayer::initAudioCapture()
{
    SLresult result;

    // configure audio source
369
    DEBUG("Configure audio source\n");
370
    SLDataLocator_IODevice deviceLocator = {SL_DATALOCATOR_IODEVICE,
371
                                            SL_IODEVICE_AUDIOINPUT,
372
                                            SL_DEFAULTDEVICEID_AUDIOINPUT,
Adrien Béraud's avatar
Adrien Béraud committed
373
                                            nullptr
374
                                           };
375
376

    SLDataSource audioSource = {&deviceLocator,
Adrien Béraud's avatar
Adrien Béraud committed
377
                                nullptr
378
                               };
379
380

    // configure audio sink
381
382
    DEBUG("Configure audio sink\n");

383
384
385
    SLDataLocator_AndroidSimpleBufferQueue bufferLocator = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
                                           NB_BUFFER_CAPTURE_QUEUE
                                                           };
386

387
    SLDataFormat_PCM audioFormat = {SL_DATAFORMAT_PCM, 1,
388
                                    SL_SAMPLINGRATE_8,
389
390
391
392
393
                                    SL_PCMSAMPLEFORMAT_FIXED_16,
                                    SL_PCMSAMPLEFORMAT_FIXED_16,
                                    SL_SPEAKER_FRONT_CENTER,
                                    SL_BYTEORDER_LITTLEENDIAN
                                   };
394

395
396
397
    SLDataSink audioSink = {&bufferLocator,
                            &audioFormat
                           };
398
399
400

    // create audio recorder
    // (requires the RECORD_AUDIO permission)
401
    DEBUG("Create audio recorder\n");
402
403
    const SLInterfaceID id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
    const SLboolean req[] = {SL_BOOLEAN_TRUE};
404

Adrien Béraud's avatar
Adrien Béraud committed
405
    if (engineInterface_ != nullptr) {
406
        result = (*engineInterface_)->CreateAudioRecorder(engineInterface_,
407
                 &recorderObject_, &audioSource, &audioSink, 1, id, req);
alision's avatar
alision committed
408
    }
409

410
    if (SL_RESULT_SUCCESS != result) {
411
        DEBUG("Error: could not create audio recorder");
412
413
414
415
        return;
    }

    // realize the audio recorder
416
    DEBUG("Realize the audio recorder\n");
417
    result = (*recorderObject_)->Realize(recorderObject_, SL_BOOLEAN_FALSE);
418

419
    if (SL_RESULT_SUCCESS != result) {
420
        DEBUG("Error: could not realize audio recorder");
421
422
423
424
        return;
    }

    // get the record interface
425
    DEBUG("Create the record interface\n");
426
    result = (*recorderObject_)->GetInterface(recorderObject_, SL_IID_RECORD, &recorderInterface_);
427
428
429
    assert(SL_RESULT_SUCCESS == result);

    // get the buffer queue interface
430
    DEBUG("Create the buffer queue interface\n");
431
    result = (*recorderObject_)->GetInterface(recorderObject_, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
432
             &recorderBufferQueue_);
433
434
435
    assert(SL_RESULT_SUCCESS == result);

    // register callback on the buffer queue
436
    DEBUG("Register the audio capture callback\n");
437
    result = (*recorderBufferQueue_)->RegisterCallback(recorderBufferQueue_, audioCaptureCallback, this);
438
439
    assert(SL_RESULT_SUCCESS == result);

440
    DEBUG("Audio capture initialized\n");
441
442
443
}


444
void
445
446
OpenSLLayer::startAudioPlayback()
{
Adrien Béraud's avatar
Adrien Béraud committed
447
    assert(nullptr != playbackBufferQueue_);
448

449
    DEBUG("Start audio playback\n");
450
451
452

    SLresult result;

453
    for (int i = 0; i < NB_BUFFER_PLAYBACK_QUEUE; i++) {
454
455
456
        AudioBuffer &buffer = getNextPlaybackBuffer();
        incrementPlaybackIndex();

457
        buffer.reset();
458

Adrien Béraud's avatar
Adrien Béraud committed
459
        result = (*playbackBufferQueue_)->Enqueue(playbackBufferQueue_, buffer.getChannel(0)->data(), buffer.frames());
460

461
        if (SL_RESULT_SUCCESS != result) {
462
            DEBUG("Error could not enqueue initial buffers\n");
463
464
465
        }
    }

466
    result = (*playerInterface_)->SetPlayState(playerInterface_, SL_PLAYSTATE_PLAYING);
467
468
    assert(SL_RESULT_SUCCESS == result);

469
    DEBUG("Audio playback started\n");
470
471
472
473
474
}

void
OpenSLLayer::startAudioCapture()
{
Adrien Béraud's avatar
Adrien Béraud committed
475
    assert(nullptr != playbackBufferQueue_);
476

477
    DEBUG("Start audio capture\n");
478
479
480

    SLresult result;

481

482
    // in case already recording, stop recording and clear buffer queue
Adrien Béraud's avatar
Adrien Béraud committed
483
    if (recorderInterface_ != nullptr) {
484
        result = (*recorderInterface_)->SetRecordState(recorderInterface_, SL_RECORDSTATE_STOPPED);
alision's avatar
alision committed
485
486
        assert(SL_RESULT_SUCCESS == result);
    }
alision's avatar
alision committed
487
488

    DEBUG("Clearing recorderBufferQueue\n");
489
    result = (*recorderBufferQueue_)->Clear(recorderBufferQueue_);
490
491
    assert(SL_RESULT_SUCCESS == result);

alision's avatar
alision committed
492
    DEBUG("getting next record buffer\n");
493
494
    // enqueue an empty buffer to be filled by the recorder
    // (for streaming recording, we enqueue at least 2 empty buffers to start things off)
495
496
497
    AudioBuffer &buffer = getNextRecordBuffer();
    incrementRecordIndex();

498
    buffer.reset();
499

alision's avatar
alision committed
500
    DEBUG("Enqueue record buffer\n");
Adrien Béraud's avatar
Adrien Béraud committed
501
    result = (*recorderBufferQueue_)->Enqueue(recorderBufferQueue_, buffer.getChannel(0)->data(), buffer.frames());
502

503
504
    // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
    // which for this code example would indicate a programming error
505
506
507
    if (SL_RESULT_SUCCESS != result) {
        DEBUG("Error could not enqueue buffers in audio capture\n");
        return;
alision's avatar
alision committed
508
    }
509
510

    // start recording
511
    result = (*recorderInterface_)->SetRecordState(recorderInterface_, SL_RECORDSTATE_RECORDING);
512
513
    assert(SL_RESULT_SUCCESS == result);

514
    DEBUG("Audio capture started\n");
515
516
517
518
519
}

void
OpenSLLayer::stopAudioPlayback()
{
520
    DEBUG("Stop audio playback\n");
521

Adrien Béraud's avatar
Adrien Béraud committed
522
    if (playerInterface_ != nullptr) {
alision's avatar
alision committed
523
        SLresult result;
524
        result = (*playerInterface_)->SetPlayState(playerInterface_, SL_PLAYSTATE_STOPPED);
alision's avatar
alision committed
525
526
527
528
        assert(SL_RESULT_SUCCESS == result);
    }

    DEBUG("Audio playback stopped\n");
529
530
531
532
533
}

void
OpenSLLayer::stopAudioCapture()
{
534
    DEBUG("Stop audio capture\n");
535

Adrien Béraud's avatar
Adrien Béraud committed
536
    if (recorderInterface_ != nullptr) {
alision's avatar
alision committed
537
        SLresult result;
538
        result = (*recorderInterface_)->SetRecordState(recorderInterface_, SL_RECORDSTATE_STOPPED);
alision's avatar
alision committed
539
540
541
542
        assert(SL_RESULT_SUCCESS == result);
    }

    DEBUG("Audio capture stopped\n");
543

544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
}

std::vector<std::string>
OpenSLLayer::getCaptureDeviceList() const
{
    std::vector<std::string> captureDeviceList;

    return captureDeviceList;
}

std::vector<std::string>
OpenSLLayer::getPlaybackDeviceList() const
{
    std::vector<std::string> playbackDeviceList;

    return playbackDeviceList;
}

562
563
void
OpenSLLayer::playback(SLAndroidSimpleBufferQueueItf queue)
564
{
Adrien Béraud's avatar
Adrien Béraud committed
565
    assert(nullptr != queue);
566

Adrien Béraud's avatar
Adrien Béraud committed
567
  //  usleep(20000);
568

569
    AudioBuffer &buffer = getNextPlaybackBuffer();
570

Adrien Béraud's avatar
Adrien Béraud committed
571
    //buffer.reset();
Alexandre Savard's avatar
Alexandre Savard committed
572

Tristan Matthews's avatar
Tristan Matthews committed
573
    const bool bufferFilled = audioPlaybackFillBuffer(buffer);
574

575
    if (bufferFilled) {
576
#ifdef RECORD_AUDIO_TODISK
Adrien Béraud's avatar
Adrien Béraud committed
577
        opensl_outfile.write((char const *)(buffer.getChannel(0)->data()), buffer.frames()*sizeof(SFLAudioSample));
578
#endif
Adrien Béraud's avatar
Adrien Béraud committed
579
        SLresult result = (*queue)->Enqueue(queue, buffer.getChannel(0)->data(), buffer.frames()*sizeof(SFLAudioSample));
580

581
        if (SL_RESULT_SUCCESS != result) {
582
            DEBUG("Error could not enqueue buffers in playback callback\n");
583
        }
584

585
        incrementPlaybackIndex();
586
587
588
    }
}

Tristan Matthews's avatar
Tristan Matthews committed
589
590
void
OpenSLLayer::audioPlaybackCallback(SLAndroidSimpleBufferQueueItf queue, void *context)
591
{
Adrien Béraud's avatar
Adrien Béraud committed
592
    assert(nullptr != context);
593
594
595
    static_cast<OpenSLLayer*>(context)->playback(queue);
}

Tristan Matthews's avatar
Tristan Matthews committed
596
597
void
OpenSLLayer::capture(SLAndroidSimpleBufferQueueItf queue)
598
{
Adrien Béraud's avatar
Adrien Béraud committed
599
    assert(nullptr != queue);
600

601
    AudioBuffer &old_buffer = getNextRecordBuffer();
602
    incrementRecordIndex();
603
    AudioBuffer &buffer = getNextRecordBuffer();
604
605
606
607
608

    SLresult result;

    // enqueue an empty buffer to be filled by the recorder
    // (for streaming recording, we enqueue at least 2 empty buffers to start things off)
Adrien Béraud's avatar
Adrien Béraud committed
609
    result = (*recorderBufferQueue_)->Enqueue(recorderBufferQueue_, buffer.getChannel(0)->data(), buffer.frames()*sizeof(SFLAudioSample));
610
611
    
    audioCaptureFillBuffer(old_buffer);
Adrien Béraud's avatar
Adrien Béraud committed
612

613
614
615
    // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
    // which for this code example would indicate a programming error
    assert(SL_RESULT_SUCCESS == result);
616
    
617
#ifdef RECORD_AUDIO_TODISK
Adrien Béraud's avatar
Adrien Béraud committed
618
    opensl_infile.write((char const *)(buffer.getChannel(0)->data()), buffer.frames()*sizeof(SFLAudioSample));
619
#endif
620
621
}

Tristan Matthews's avatar
Tristan Matthews committed
622
623
void
OpenSLLayer::audioCaptureCallback(SLAndroidSimpleBufferQueueItf queue, void *context)
624
{
Adrien Béraud's avatar
Adrien Béraud committed
625
    assert(nullptr != context);
626
627
628
    static_cast<OpenSLLayer*>(context)->capture(queue);
}

Tristan Matthews's avatar
Tristan Matthews committed
629
630
void
OpenSLLayer::updatePreference(AudioPreference &preference, int index, PCMType type)
631
632
{
#ifdef OUTSIDE_TESTING
633

634
635
636
    switch (type) {
        case SFL_PCM_PLAYBACK:
            break;
637

638
        case SFL_PCM_CAPTURE:
639
            break;
640

641
        case SFL_PCM_RINGTONE:
642
            break;
643

644
645
646
        default:
            break;
    }
647

648
649
#endif
}
650
651
652
653
654

bool OpenSLLayer::audioPlaybackFillBuffer(AudioBuffer &buffer)
{
    // Looks if there's any voice audio from rtp to be played
    MainBuffer &mbuffer = Manager::instance().getMainBuffer();
Adrien Béraud's avatar
Adrien Béraud committed
655
656
    size_t samplesToGet = mbuffer.availableForGet(MainBuffer::DEFAULT_ID);
    size_t urgentSamplesToGet = urgentRingBuffer_.availableForGet(MainBuffer::DEFAULT_ID);
657
658
659
660
661
662
663
664
665
666

    PlaybackMode mode = getPlaybackMode();

    bool bufferFilled = false;

    switch (mode) {
        case NONE:
        case TONE:
        case RINGTONE:
        case URGENT: {
Adrien Béraud's avatar
Adrien Béraud committed
667
668
            if (urgentSamplesToGet > 0)
                bufferFilled = audioPlaybackFillWithUrgent(buffer, urgentSamplesToGet);
669
670
671
672
            else
                bufferFilled = audioPlaybackFillWithToneOrRingtone(buffer);
        }
        break;
Adrien Béraud's avatar
Adrien Béraud committed
673
    
674
        case VOICE: {
Adrien Béraud's avatar
Adrien Béraud committed
675
676
            if (samplesToGet > 0)
                bufferFilled = audioPlaybackFillWithVoice(buffer, samplesToGet);
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
            else {
                buffer.reset();
                bufferFilled = true;
            }
        }
        break;

        case ZEROS:
        default: {
            buffer.reset();
            bufferFilled = true;
        }
    }

    if (!bufferFilled)
Adrien Béraud's avatar
Adrien Béraud committed
692
        DEBUG("Error buffer not filled in audio playback\n");
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729

    return bufferFilled;
}

// #define RECORD_TOMAIN_TODISK
#ifdef RECORD_TOMAIN_TODISK
#include <fstream>
std::ofstream opensl_tomainbuffer("/data/data/com.savoirfairelinux.sflphone/opensl_tomain.raw", std::ofstream::out | std::ofstream::binary);
#endif

void OpenSLLayer::audioCaptureFillBuffer(AudioBuffer &buffer)
{
    MainBuffer &mbuffer = Manager::instance().getMainBuffer();

    const unsigned mainBufferSampleRate = mbuffer.getInternalSamplingRate();
    const bool resample = mainBufferSampleRate != sampleRate_;

    buffer.applyGain(captureGain_);

    if (resample) {
        AudioBuffer out(buffer);
        out.setSampleRate(sampleRate_);

        converter_.resample(buffer, out);
        dcblocker_.process(out);
        mbuffer.putData(out, MainBuffer::DEFAULT_ID);
    } else {
        dcblocker_.process(buffer);
#ifdef RECORD_TOMAIN_TODISK
        opensl_tomainbuffer.write((char const *)in_ptr, toGetBytes /);
#endif
        mbuffer.putData(buffer, MainBuffer::DEFAULT_ID);
    }
}

bool OpenSLLayer::audioPlaybackFillWithToneOrRingtone(AudioBuffer &buffer)
{
Adrien Béraud's avatar
Adrien Béraud committed
730
    buffer.resize(BUFFER_SIZE);
731
732
733
    AudioLoop *tone = Manager::instance().getTelephoneTone();
    AudioLoop *file_tone = Manager::instance().getTelephoneFile();

Adrien Béraud's avatar
Adrien Béraud committed
734
735
    // In case of a dtmf, the pointers will be set to nullptr once the dtmf length is
    // reached. For this reason we need to fill audio buffer with zeros if pointer is nullptr
736
737
738
739
740
741
742
743
744
745
746
    if (tone) {
        tone->getNext(buffer, playbackGain_);
    } else if (file_tone) {
        file_tone->getNext(buffer, playbackGain_);
    } else {
        buffer.reset();
    }

    return true;
}

Adrien Béraud's avatar
Adrien Béraud committed
747
bool OpenSLLayer::audioPlaybackFillWithUrgent(AudioBuffer &buffer, size_t samplesToGet)
748
749
{
    // Urgent data (dtmf, incoming call signal) come first.
750
    samplesToGet = std::min(samplesToGet, BUFFER_SIZE);
Adrien Béraud's avatar
Adrien Béraud committed
751
    buffer.resize(samplesToGet);
752
753
754
    urgentRingBuffer_.get(buffer, MainBuffer::DEFAULT_ID);
    buffer.applyGain(playbackGain_);

Adrien Béraud's avatar
Adrien Béraud committed
755
756
    // Consume the regular one as well (same amount of samples)
    Manager::instance().getMainBuffer().discard(samplesToGet, MainBuffer::DEFAULT_ID);
757
758
759
760

    return true;
}

Adrien Béraud's avatar
Adrien Béraud committed
761
bool OpenSLLayer::audioPlaybackFillWithVoice(AudioBuffer &buffer, size_t samplesAvail)
762
{
Adrien Béraud's avatar
Adrien Béraud committed
763
    //const size_t samplesToCpy = buffer.samples();
764

Adrien Béraud's avatar
Adrien Béraud committed
765
    if (samplesAvail == 0)
766
767
768
769
        return false;

    MainBuffer &mainBuffer = Manager::instance().getMainBuffer();

Adrien Béraud's avatar
Adrien Béraud committed
770
    buffer.resize(samplesAvail);
771
772
773
774
    mainBuffer.getData(buffer, MainBuffer::DEFAULT_ID);
    buffer.applyGain(getPlaybackGain());

    if (sampleRate_ != mainBuffer.getInternalSamplingRate()) {
Adrien Béraud's avatar
Adrien Béraud committed
775
        DEBUG("OpenSLLayer::audioPlaybackFillWithVoice sampleRate_ != mainBuffer.getInternalSamplingRate() \n");
776
777
778
        AudioBuffer out(buffer, false);
        out.setSampleRate(sampleRate_);
        converter_.resample(buffer, out);
779
        buffer = out;
780
781
782
783
    }

    return true;
}