1ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* 2ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project 3ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * 4ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 5ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * you may not use this file except in compliance with the License. 6ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * You may obtain a copy of the License at 7ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * 8ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 9ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * 10ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 11ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 12ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * See the License for the specific language governing permissions and 14ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * limitations under the License. 15ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi */ 16ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten/* Audio Record Test 187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 197126c25d7c037e5086216cf540ecf40779c3585aGlenn KastenFirst run the program from shell: 205be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten % adb shell slesTest_recBuffQueue /sdcard/myrec.wav 217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 227126c25d7c037e5086216cf540ecf40779c3585aGlenn KastenThese use adb on host to retrive the file: 235be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten % adb pull /sdcard/myrec.wav 24ecccdd9e99a753d3a9e105ec4b9b02e7afe60ebeGlenn Kasten 257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten*/ 267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 28ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#include <stdlib.h> 29ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#include <stdio.h> 30ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#include <string.h> 31ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#include <unistd.h> 32ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#include <sys/time.h> 33ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#include <fcntl.h> 345be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten#include <system/audio.h> 355be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten#include <audio_utils/primitives.h> 365be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten#include <audio_utils/sndfile.h> 37ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 38c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h> 39c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES_Android.h> 40ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 415be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kastenaudio_format_t transferFormat = AUDIO_FORMAT_DEFAULT; 425be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kastenuint32_t sampleRate = 48000; 435be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kastenint channelCount = 1; 445be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kastenbool useIndexChannelMask = false; 455be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kastensize_t frameSize; 465be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten 474dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten/* Preset number to use for recording */ 484dd1fab74463de4852b86af64481006f87d48b54Glenn KastenSLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_NONE; 494dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten 5001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten/* Explicitly requesting SL_IID_ANDROIDSIMPLEBUFFERQUEUE and SL_IID_ANDROIDCONFIGURATION 51b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi * on the AudioRecorder object */ 52b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi#define NUM_EXPLICIT_INTERFACES_FOR_RECORDER 2 53ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 54ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* Size of the recording buffer queue */ 55ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#define NB_BUFFERS_IN_QUEUE 1 56ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* Size of each buffer in the queue */ 575be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten#define BUFFER_SIZE_IN_BYTES 2048 58ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 59ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* Local storage for Audio data */ 60ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Triviint8_t pcmData[NB_BUFFERS_IN_QUEUE * BUFFER_SIZE_IN_BYTES]; 61ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 62ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* destination for recorded data */ 635be7f78e0e9823393e9d72064a761408bd9c9023Glenn KastenSNDFILE *sndfile; 64ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 65ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi//----------------------------------------------------------------- 66ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* Exits the application if an error is encountered */ 67ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__) 68ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 69ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivivoid ExitOnErrorFunc( SLresult result , int line) 70ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi{ 71ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi if (SL_RESULT_SUCCESS != result) { 725be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten fprintf(stderr, "%u error code encountered at line %d, exiting\n", result, line); 73c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten exit(EXIT_FAILURE); 74ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi } 75ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi} 76ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 77ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi//----------------------------------------------------------------- 78ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* Structure for passing information to callback function */ 79ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivitypedef struct CallbackCntxt_ { 80ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLPlayItf playItf; 81ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLuint32 size; 82ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLint8* pDataBase; // Base address of local audio data storage 83ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLint8* pData; // Current address of local audio data storage 84ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi} CallbackCntxt; 85ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 869bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi 879bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi//----------------------------------------------------------------- 889bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi/* Callback for recording buffer queue events */ 899bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivivoid RecCallback( 909bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi SLRecordItf caller, 91086a6f51a7b12880ed114962136972f89ed70da2Glenn Kasten void *pContext __unused, 929bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi SLuint32 event) 939bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi{ 949bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi if (SL_RECORDEVENT_HEADATNEWPOS & event) { 959bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi SLmillisecond pMsec = 0; 969bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi (*caller)->GetPosition(caller, &pMsec); 975be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("SL_RECORDEVENT_HEADATNEWPOS current position=%ums\n", pMsec); 989bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi } 999bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi 1009bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi if (SL_RECORDEVENT_HEADATMARKER & event) { 1019bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi SLmillisecond pMsec = 0; 1029bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi (*caller)->GetPosition(caller, &pMsec); 1035be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("SL_RECORDEVENT_HEADATMARKER current position=%ums\n", pMsec); 1049bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi } 1059bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi} 1069bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi 107ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi//----------------------------------------------------------------- 108ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/* Callback for recording buffer queue events */ 109ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivivoid RecBufferQueueCallback( 11001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLAndroidSimpleBufferQueueItf queueItf, 111ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi void *pContext) 112ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi{ 1135be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten //printf("RecBufferQueueCallback called\n"); 114ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 115ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi CallbackCntxt *pCntxt = (CallbackCntxt*)pContext; 116ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 117ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Save the recorded data */ 1185be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten sf_count_t frameCount = BUFFER_SIZE_IN_BYTES / frameSize; 1195be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten switch (transferFormat) { 1205be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_8_BIT: { 1215be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten short temp[BUFFER_SIZE_IN_BYTES]; 1225be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten memcpy_to_i16_from_u8(temp, (const unsigned char *) pCntxt->pDataBase, BUFFER_SIZE_IN_BYTES); 1235be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten (void) sf_writef_short(sndfile, (const short *) temp, frameCount); 1245be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } break; 1255be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_16_BIT: 1265be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten (void) sf_writef_short(sndfile, (const short *) pCntxt->pDataBase, frameCount); 1275be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 1285be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_32_BIT: 1295be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten (void) sf_writef_int(sndfile, (const int *) pCntxt->pDataBase, frameCount); 1305be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 1315be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_FLOAT: 1325be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten (void) sf_writef_float(sndfile, (const float *) pCntxt->pDataBase, frameCount); 1335be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 1345be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten default: 1355be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten fprintf(stderr, "Unsupported transfer format %d\n", transferFormat); 1365be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten exit(EXIT_FAILURE); 1375be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } 138ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 139ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Increase data pointer by buffer size */ 140ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi pCntxt->pData += BUFFER_SIZE_IN_BYTES; 141ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 142ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi if (pCntxt->pData >= pCntxt->pDataBase + (NB_BUFFERS_IN_QUEUE * BUFFER_SIZE_IN_BYTES)) { 143ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi pCntxt->pData = pCntxt->pDataBase; 144ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi } 145ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 146ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError( (*queueItf)->Enqueue(queueItf, pCntxt->pDataBase, BUFFER_SIZE_IN_BYTES) ); 147ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 14801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLAndroidSimpleBufferQueueState recQueueState; 149ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError( (*queueItf)->GetState(queueItf, &recQueueState) ); 150ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 15104c7354b8a9afcf2151c00c1dfbc64d0ba5d33ccGlenn Kasten /*fprintf(stderr, "\tRecBufferQueueCallback now has pCntxt->pData=%p queue: " 15258432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten "count=%u playIndex=%u\n", 15304c7354b8a9afcf2151c00c1dfbc64d0ba5d33ccGlenn Kasten pCntxt->pData, recQueueState.count, recQueueState.index);*/ 1545be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten //printf("RecBufferQueueCallback returned\n"); 155ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi} 156ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 157ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi//----------------------------------------------------------------- 158ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 15964ae6e1913b9330ad7ebd1c3ae62cdcf2d45b758Jean-Michel Trivi/* Record to an audio path by opening a file descriptor on that path */ 160ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivivoid TestRecToBuffQueue( SLObjectItf sl, const char* path, SLAint64 durationInSeconds) 161ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi{ 1625be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten SF_INFO info; 1635be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten info.frames = 0; 1645be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten info.samplerate = sampleRate; 1655be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten info.channels = channelCount; 1665be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten switch (transferFormat) { 1675be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_8_BIT: 1685be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_U8; 1695be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 1705be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_16_BIT: 1715be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; 1725be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 1735be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_32_BIT: 1745be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_32; 1755be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 1765be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_FLOAT: 1775be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; 1785be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 1795be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten default: 1805be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten fprintf(stderr, "Unsupported transfer format %d\n", transferFormat); 1815be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten exit(EXIT_FAILURE); 1825be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } 1835be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten sndfile = sf_open(path, SFM_WRITE, &info); 1845be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten if (sndfile == NULL) { 185ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(SL_RESULT_RESOURCE_ERROR); 186ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi } 187ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 188ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLresult result; 189ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLEngineItf EngineItf; 190ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 191ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Objects this application uses: one audio recorder */ 192ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLObjectItf recorder; 193ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 194ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Interfaces for the audio recorder */ 19501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLAndroidSimpleBufferQueueItf recBuffQueueItf; 196b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi SLRecordItf recordItf; 197b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi SLAndroidConfigurationItf configItf; 198ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 199ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Source of audio data for the recording */ 200ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLDataSource recSource; 201ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLDataLocator_IODevice ioDevice; 202ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 203ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Data sink for recorded audio */ 204ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLDataSink recDest; 20501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLDataLocator_AndroidSimpleBufferQueue recBuffQueue; 2065be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten /* As mentioned in the Android extension API documentation this is identical to 2075be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten * OpenSL ES 1.1 SLDataFormat_PCM_EX, and can be used for an instance of SLDataFormat_PCM. 2085be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten */ 2095be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten SLAndroidDataFormat_PCM_EX pcm; 210ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 211ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLboolean required[NUM_EXPLICIT_INTERFACES_FOR_RECORDER]; 212ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLInterfaceID iidArray[NUM_EXPLICIT_INTERFACES_FOR_RECORDER]; 213ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 214ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Get the SL Engine Interface which is implicit */ 215ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf); 216ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 217ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 218ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Initialize arrays required[] and iidArray[] */ 219ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi for (int i=0 ; i < NUM_EXPLICIT_INTERFACES_FOR_RECORDER ; i++) { 220ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi required[i] = SL_BOOLEAN_FALSE; 221ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi iidArray[i] = SL_IID_NULL; 222ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi } 223ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 224ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 225ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* ------------------------------------------------------ */ 226ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Configuration of the recorder */ 227ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 22801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten /* Request the AndroidSimpleBufferQueue and AndroidConfiguration interfaces */ 229ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi required[0] = SL_BOOLEAN_TRUE; 23001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten iidArray[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; 231b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi required[1] = SL_BOOLEAN_TRUE; 232b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi iidArray[1] = SL_IID_ANDROIDCONFIGURATION; 233ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 234ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Setup the data source */ 235ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ioDevice.locatorType = SL_DATALOCATOR_IODEVICE; 236ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ioDevice.deviceType = SL_IODEVICE_AUDIOINPUT; 237ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ioDevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 238ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ioDevice.device = NULL; 239ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi recSource.pLocator = (void *) &ioDevice; 2402246c698482ab6860906672229f0ae6d886e6302Glenn Kasten recSource.pFormat = NULL; 241ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 242ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Setup the data sink */ 24301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten recBuffQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 244ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi recBuffQueue.numBuffers = NB_BUFFERS_IN_QUEUE; 245ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* set up the format of the data in the buffer queue */ 2465be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.formatType = transferFormat == AUDIO_FORMAT_PCM_FLOAT || 2475be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten transferFormat == AUDIO_FORMAT_PCM_8_BIT ? 2485be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten SL_ANDROID_DATAFORMAT_PCM_EX : SL_DATAFORMAT_PCM; 2495be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.numChannels = channelCount; 2505be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.sampleRate = sampleRate * 1000; // milliHz 2515be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.representation = SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT; 2525be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten switch (transferFormat) { 2535be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_16_BIT: 2545be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 2555be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.containerSize = 16; 2565be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 2575be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_32_BIT: 2585be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_32; 2595be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.containerSize = 32; 2605be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 2615be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_8_BIT: 2625be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_8; 2635be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.containerSize = 8; 2645be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.representation = SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT; 2655be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 2665be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case AUDIO_FORMAT_PCM_FLOAT: 2675be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.bitsPerSample = 32; 2685be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.containerSize = 32; 2695be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT; 2705be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 2715be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten default: 2725be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten fprintf(stderr, "Unsupported transfer format %d\n", transferFormat); 2735be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten exit(EXIT_FAILURE); 2745be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } 2755be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten if (useIndexChannelMask) { 2765be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.channelMask = (1 << channelCount) - 1; 2775be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } else { 2785be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten switch (channelCount) { 2795be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case 1: 2805be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.channelMask = SL_SPEAKER_FRONT_LEFT; 2815be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 2825be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case 2: 2835be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 2845be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 2855be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten default: 2865be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten fprintf(stderr, "Unsupported channel count %d\n", channelCount); 2875be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten exit(EXIT_FAILURE); 2885be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } 2895be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } 290ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 291ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 292ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi recDest.pLocator = (void *) &recBuffQueue; 293ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi recDest.pFormat = (void * ) &pcm; 294ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 295ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Create the audio recorder */ 296b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi result = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recDest, 297b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi NUM_EXPLICIT_INTERFACES_FOR_RECORDER, iidArray, required); 298ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 2995be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Recorder created\n"); 300ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 301b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi /* Get the Android configuration interface which is explicit */ 302b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi result = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDCONFIGURATION, (void*)&configItf); 303b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi ExitOnError(result); 304b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi 305b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi /* Use the configuration interface to configure the recorder before it's realized */ 3064dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) { 3074dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET, 3084dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten &presetValue, sizeof(SLuint32)); 3094dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten ExitOnError(result); 3105be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Recorder configured with preset %u\n", presetValue); 3114dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten } else { 3124dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten printf("Using default record preset\n"); 3134dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten } 314b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi 3154dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten SLuint32 presetRetrieved = SL_ANDROID_RECORDING_PRESET_NONE; 316b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi SLuint32 presetSize = 2*sizeof(SLuint32); // intentionally too big 317b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi result = (*configItf)->GetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET, 3184dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten &presetSize, (void*)&presetRetrieved); 319b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi ExitOnError(result); 3204dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten if (presetValue == SL_ANDROID_RECORDING_PRESET_NONE) { 3214dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten printf("The default record preset appears to be %u\n", presetRetrieved); 3224dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten } else if (presetValue != presetRetrieved) { 32368686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten fprintf(stderr, "Error retrieving recording preset as %u instead of %u\n", presetRetrieved, 32468686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten presetValue); 325b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi ExitOnError(SL_RESULT_INTERNAL_ERROR); 326b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi } 327b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi 328ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Realize the recorder in synchronous mode. */ 329ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*recorder)->Realize(recorder, SL_BOOLEAN_FALSE); 330ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 3315be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Recorder realized\n"); 332ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 333ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Get the record interface which is implicit */ 334ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*recorder)->GetInterface(recorder, SL_IID_RECORD, (void*)&recordItf); 335ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 336ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 3379bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi /* Set up the recorder callback to get events during the recording */ 3389bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi result = (*recordItf)->SetMarkerPosition(recordItf, 2000); 3399bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi ExitOnError(result); 3409bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi result = (*recordItf)->SetPositionUpdatePeriod(recordItf, 500); 3419bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi ExitOnError(result); 3429bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi result = (*recordItf)->SetCallbackEventsMask(recordItf, 3439bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi SL_RECORDEVENT_HEADATMARKER | SL_RECORDEVENT_HEADATNEWPOS); 3449bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi ExitOnError(result); 3459bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi result = (*recordItf)->RegisterCallback(recordItf, RecCallback, NULL); 3469bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi ExitOnError(result); 3475be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Recorder callback registered\n"); 3489bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi 349ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Get the buffer queue interface which was explicitly requested */ 3505e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten result = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 3515e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten (void*)&recBuffQueueItf); 352ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 353ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 354ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* ------------------------------------------------------ */ 355ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Initialize the callback and its context for the recording buffer queue */ 356ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi CallbackCntxt cntxt; 357ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi cntxt.pDataBase = (int8_t*)&pcmData; 358ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi cntxt.pData = cntxt.pDataBase; 359ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi cntxt.size = sizeof(pcmData); 360ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*recBuffQueueItf)->RegisterCallback(recBuffQueueItf, RecBufferQueueCallback, &cntxt); 361ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 362ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 363ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Enqueue buffers to map the region of memory allocated to store the recorded data */ 3645be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Enqueueing buffer "); 365ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi for(int i = 0 ; i < NB_BUFFERS_IN_QUEUE ; i++) { 3665be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("%d ", i); 367ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*recBuffQueueItf)->Enqueue(recBuffQueueItf, cntxt.pData, BUFFER_SIZE_IN_BYTES); 368ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 369ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi cntxt.pData += BUFFER_SIZE_IN_BYTES; 370ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi } 3715be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("\n"); 372ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi cntxt.pData = cntxt.pDataBase; 373ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 374ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* ------------------------------------------------------ */ 375ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Start recording */ 376ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING); 377ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 3785be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Starting to record\n"); 379ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 380ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Record for at least a second */ 381ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi if (durationInSeconds < 1) { 382ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi durationInSeconds = 1; 383ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi } 384ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi usleep(durationInSeconds * 1000 * 1000); 385ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 386ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* ------------------------------------------------------ */ 387ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* End of recording */ 388ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 389ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Stop recording */ 390ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); 391ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 3925be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Stopped recording\n"); 393ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 394ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Destroy the AudioRecorder object */ 395ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi (*recorder)->Destroy(recorder); 396ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 3975be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten sf_close(sndfile); 398ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi} 399ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 400ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi//----------------------------------------------------------------- 401ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Triviint main(int argc, char* const argv[]) 402ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi{ 4035be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten int durationInSeconds = 10; 404ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLresult result; 405ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLObjectItf sl; 406ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 4074dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten const char *prog = argv[0]; 4085be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("OpenSL ES test %s: exercises SLRecordItf and SLAndroidSimpleBufferQueueItf ", 4094dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten prog); 4105be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("on an AudioRecorder object\n"); 411ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 4124dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten int i; 4134dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten for (i = 1; i < argc; ++i) { 4144dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten const char *arg = argv[i]; 4154dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten if (arg[0] != '-') { 4164dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten break; 4174dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten } 4184dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten switch (arg[1]) { 4195be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case 'c': // channel count 4205be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten channelCount = atoi(&arg[2]); 4215be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4225be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case 'd': // duration in seconds 4235be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten durationInSeconds = atoi(&arg[2]); 4245be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4255be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case 'f': 4265be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten transferFormat = AUDIO_FORMAT_PCM_FLOAT; 4275be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4285be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case 'i': 4295be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten useIndexChannelMask = true; 4305be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4314dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten case 'p': // preset number 4324dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten presetValue = atoi(&arg[2]); 4334dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten break; 4345be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case 'r': 4355be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten sampleRate = atoi(&arg[2]); 4365be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4375be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case '1': 4385be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten transferFormat = AUDIO_FORMAT_PCM_8_BIT; 4395be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4405be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case '2': 4415be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten transferFormat = AUDIO_FORMAT_PCM_16_BIT; 4425be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4435be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten case '4': 4445be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten transferFormat = AUDIO_FORMAT_PCM_32_BIT; 4455be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten break; 4464dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten default: 4474dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten fprintf(stderr, "%s: unknown option %s\n", prog, arg); 4484dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten break; 4494dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten } 4504dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten } 4514dd1fab74463de4852b86af64481006f87d48b54Glenn Kasten 4525be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten if (transferFormat == AUDIO_FORMAT_DEFAULT) { 4535be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten transferFormat = AUDIO_FORMAT_PCM_16_BIT; 4545be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten } 4555be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten frameSize = audio_bytes_per_sample(transferFormat) * channelCount; 4565be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten 4575be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten if (argc-i != 1) { 4585be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Usage: \t%s [-c#] [-d#] [-i] [-p#] [-r#] [-1/2/4/f] destination_file\n", prog); 4595be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf(" -c# channel count, defaults to 1\n"); 4605be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf(" -d# duration in seconds, default to 10\n"); 4615be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf(" -i index channel mask, not yet implemented\n"); 46268686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten printf(" -p# is the preset value which defaults to SL_ANDROID_RECORDING_PRESET_NONE\n"); 46368686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten printf(" possible values are:\n"); 46468686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten printf(" -p%d SL_ANDROID_RECORDING_PRESET_NONE\n", 46568686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten SL_ANDROID_RECORDING_PRESET_NONE); 46668686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten printf(" -p%d SL_ANDROID_RECORDING_PRESET_GENERIC\n", 46768686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten SL_ANDROID_RECORDING_PRESET_GENERIC); 46868686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten printf(" -p%d SL_ANDROID_RECORDING_PRESET_CAMCORDER\n", 46968686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten SL_ANDROID_RECORDING_PRESET_CAMCORDER); 47068686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten printf(" -p%d SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION\n", 47168686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION); 47268686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten printf(" -p%d SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION\n", 47368686bd0cb31f99f07ebc176176f8b51adf8d1d5Glenn Kasten SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION); 4745be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf(" -r# sample rate in Hz, defaults to 48000\n"); 4755be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf(" -[1/2/4/f] sample format: 8-bit unsigned, 16-bit signed, 32-bit signed, float, " 4765be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten "defaults to 16-bit signed\n"); 4775be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten printf("Example: \"%s /sdcard/myrec.wav\" \n", prog); 478c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten exit(EXIT_FAILURE); 479ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi } 480ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 481ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi SLEngineOption EngineOption[] = { 482ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE} 483ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi }; 484ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 485ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL); 486ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 487ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 488ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Realizing the SL Engine in synchronous mode. */ 489ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); 490ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi ExitOnError(result); 491ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 4925be7f78e0e9823393e9d72064a761408bd9c9023Glenn Kasten TestRecToBuffQueue(sl, argv[i], durationInSeconds); 493ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 494ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi /* Shutdown OpenSL ES */ 495ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi (*sl)->Destroy(sl); 496ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi 497c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten return EXIT_SUCCESS; 498ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi} 499