1f7c85330SMatthias Ringwald /* 2f7c85330SMatthias Ringwald * Copyright (C) 2016 BlueKitchen GmbH 3f7c85330SMatthias Ringwald * 4f7c85330SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5f7c85330SMatthias Ringwald * modification, are permitted provided that the following conditions 6f7c85330SMatthias Ringwald * are met: 7f7c85330SMatthias Ringwald * 8f7c85330SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9f7c85330SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10f7c85330SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11f7c85330SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12f7c85330SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13f7c85330SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14f7c85330SMatthias Ringwald * contributors may be used to endorse or promote products derived 15f7c85330SMatthias Ringwald * from this software without specific prior written permission. 16f7c85330SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17f7c85330SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18f7c85330SMatthias Ringwald * monetary gain. 19f7c85330SMatthias Ringwald * 20f7c85330SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21f7c85330SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22f7c85330SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23f7c85330SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24f7c85330SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25f7c85330SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26f7c85330SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27f7c85330SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28f7c85330SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29f7c85330SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30f7c85330SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31f7c85330SMatthias Ringwald * SUCH DAMAGE. 32f7c85330SMatthias Ringwald * 33f7c85330SMatthias Ringwald * Please inquire about commercial licensing options at 34f7c85330SMatthias Ringwald * [email protected] 35f7c85330SMatthias Ringwald * 36f7c85330SMatthias Ringwald */ 37f7c85330SMatthias Ringwald 38f7c85330SMatthias Ringwald /* 39f7c85330SMatthias Ringwald * sco_demo_util.c - send/receive test data via SCO, used by hfp_*_demo and hsp_*_demo 40f7c85330SMatthias Ringwald */ 41f7c85330SMatthias Ringwald 422ec72fbbSMilanka Ringwald 432ec72fbbSMilanka Ringwald #include <stdio.h> 442ec72fbbSMilanka Ringwald 45f7c85330SMatthias Ringwald #include "sco_demo_util.h" 46fcb08cdbSMilanka Ringwald #include "btstack_debug.h" 470c87db9eSMilanka Ringwald #include "btstack_sbc.h" 48379d044eSMilanka Ringwald #include "btstack_cvsd_plc.h" 49220eb563SMilanka Ringwald #include "hfp_msbc.h" 50220eb563SMilanka Ringwald #include "hfp.h" 51fcb08cdbSMilanka Ringwald 52*fbc7c9f2SMilanka Ringwald #include "wav_util.h" 53*fbc7c9f2SMilanka Ringwald 54f7c85330SMatthias Ringwald // configure test mode 55f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_SINE 0 56f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_ASCII 1 57f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_COUNTER 2 58f7c85330SMatthias Ringwald 598b29cfc6SMatthias Ringwald 60f7c85330SMatthias Ringwald // SCO demo configuration 61fcb08cdbSMilanka Ringwald #define SCO_DEMO_MODE SCO_DEMO_MODE_SINE 62f7c85330SMatthias Ringwald #define SCO_REPORT_PERIOD 100 63f7c85330SMatthias Ringwald 648b29cfc6SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO 658b29cfc6SMatthias Ringwald #define SCO_WAV_FILENAME "sco_input.wav" 66d5e5f834SMatthias Ringwald #define SCO_MSBC_OUT_FILENAME "sco_output.msbc" 67d5e5f834SMatthias Ringwald #define SCO_MSBC_IN_FILENAME "sco_input.mscb" 68220eb563SMilanka Ringwald 69202da317SMilanka Ringwald #define SCO_WAV_DURATION_IN_SECONDS 15 708b29cfc6SMatthias Ringwald #endif 718b29cfc6SMatthias Ringwald 72f7c85330SMatthias Ringwald 73f7c85330SMatthias Ringwald #if defined(HAVE_PORTAUDIO) && (SCO_DEMO_MODE == SCO_DEMO_MODE_SINE) 74f7c85330SMatthias Ringwald #define USE_PORTAUDIO 75f7c85330SMatthias Ringwald #endif 76f7c85330SMatthias Ringwald 77f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 78f7c85330SMatthias Ringwald #include <portaudio.h> 798b29cfc6SMatthias Ringwald // portaudio config 808b29cfc6SMatthias Ringwald #define NUM_CHANNELS 1 818b29cfc6SMatthias Ringwald #define SAMPLE_RATE 8000 828b29cfc6SMatthias Ringwald #define FRAMES_PER_BUFFER 24 838b29cfc6SMatthias Ringwald #define PA_SAMPLE_TYPE paInt8 84f7c85330SMatthias Ringwald // portaudio globals 85f7c85330SMatthias Ringwald static PaStream * stream; 86f7c85330SMatthias Ringwald #endif 87f7c85330SMatthias Ringwald 88fcb08cdbSMilanka Ringwald 89fcb08cdbSMilanka Ringwald static int dump_data = 1; 90fcb08cdbSMilanka Ringwald 91fcb08cdbSMilanka Ringwald static int count_sent = 0; 92fcb08cdbSMilanka Ringwald static int count_received = 0; 93d76591efSMatthias Ringwald static uint8_t negotiated_codec = 0; 94220eb563SMilanka Ringwald static int num_audio_frames = 0; 95fcb08cdbSMilanka Ringwald 96d5e5f834SMatthias Ringwald FILE * msbc_file_in; 97d5e5f834SMatthias Ringwald FILE * msbc_file_out; 987294d009SMatthias Ringwald 99f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 100d6a06398SMatthias Ringwald 101f7c85330SMatthias Ringwald 1028b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 1038b29cfc6SMatthias Ringwald 1048b29cfc6SMatthias Ringwald static int num_samples_to_write; 1058b29cfc6SMatthias Ringwald 1062afeea7fSMilanka Ringwald static btstack_sbc_decoder_state_t decoder_state; 10782e01da0SMilanka Ringwald static btstack_cvsd_plc_state_t cvsd_plc_state; 1088b29cfc6SMatthias Ringwald 109fcb08cdbSMilanka Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ 110fcb08cdbSMilanka Ringwald log_info("handle_pcm_data num samples %u / %u", num_samples, num_samples_to_write); 111fcb08cdbSMilanka Ringwald if (!num_samples_to_write) return; 112fcb08cdbSMilanka Ringwald 113fcb08cdbSMilanka Ringwald num_samples = btstack_min(num_samples, num_samples_to_write); 114fcb08cdbSMilanka Ringwald num_samples_to_write -= num_samples; 115fcb08cdbSMilanka Ringwald 116*fbc7c9f2SMilanka Ringwald wav_writer_write_int16(num_samples, data); 117fcb08cdbSMilanka Ringwald 118fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 119fcb08cdbSMilanka Ringwald sco_demo_close(); 120fcb08cdbSMilanka Ringwald } 121fcb08cdbSMilanka Ringwald } 122fcb08cdbSMilanka Ringwald 123220eb563SMilanka Ringwald static void sco_demo_fill_audio_frame(void){ 124220eb563SMilanka Ringwald if (!hfp_msbc_can_encode_audio_frame_now()) return; 125*fbc7c9f2SMilanka Ringwald int num_samples = hfp_msbc_num_audio_samples_per_frame(); 126*fbc7c9f2SMilanka Ringwald int16_t sample_buffer[num_samples]; 127*fbc7c9f2SMilanka Ringwald wav_synthesize_sine_wave_int16(num_samples, sample_buffer); 128d6a06398SMatthias Ringwald hfp_msbc_encode_audio_frame(sample_buffer); 129220eb563SMilanka Ringwald num_audio_frames++; 130220eb563SMilanka Ringwald } 131fcb08cdbSMilanka Ringwald 132fcb08cdbSMilanka Ringwald static void sco_demo_init_mSBC(void){ 133*fbc7c9f2SMilanka Ringwald int sample_rate = 16000; 134*fbc7c9f2SMilanka Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate); 135*fbc7c9f2SMilanka Ringwald btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL); 136fcb08cdbSMilanka Ringwald 137*fbc7c9f2SMilanka Ringwald num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 138220eb563SMilanka Ringwald 139220eb563SMilanka Ringwald hfp_msbc_init(); 140220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 141973d7173SMatthias Ringwald 142d5e5f834SMatthias Ringwald #ifdef SCO_MSBC_IN_FILENAME 143d5e5f834SMatthias Ringwald msbc_file_in = fopen(SCO_MSBC_IN_FILENAME, "wb"); 144d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC in file %s, %p\n", SCO_MSBC_IN_FILENAME, msbc_file_in); 145d5e5f834SMatthias Ringwald #endif 1467294d009SMatthias Ringwald #ifdef SCO_MSBC_OUT_FILENAME 147d5e5f834SMatthias Ringwald msbc_file_out = fopen(SCO_MSBC_OUT_FILENAME, "wb"); 148d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC out file %s, %p\n", SCO_MSBC_OUT_FILENAME, msbc_file_out); 1497294d009SMatthias Ringwald #endif 150fcb08cdbSMilanka Ringwald } 151fcb08cdbSMilanka Ringwald 152fcb08cdbSMilanka Ringwald static void sco_demo_receive_mSBC(uint8_t * packet, uint16_t size){ 153fcb08cdbSMilanka Ringwald if (num_samples_to_write){ 154d5e5f834SMatthias Ringwald if (msbc_file_in){ 155d5e5f834SMatthias Ringwald // log incoming mSBC data for testing 156d5e5f834SMatthias Ringwald fwrite(packet+3, size-3, 1, msbc_file_in); 157d5e5f834SMatthias Ringwald } 1582afeea7fSMilanka Ringwald btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3); 159fcb08cdbSMilanka Ringwald dump_data = 0; 160fcb08cdbSMilanka Ringwald } 161fcb08cdbSMilanka Ringwald } 162fcb08cdbSMilanka Ringwald 163*fbc7c9f2SMilanka Ringwald static void sco_demo_init_CVSD(void){ 164*fbc7c9f2SMilanka Ringwald int sample_rate = 8000; 165*fbc7c9f2SMilanka Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate); 166*fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_init(&cvsd_plc_state); 167*fbc7c9f2SMilanka Ringwald num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 168*fbc7c9f2SMilanka Ringwald } 169*fbc7c9f2SMilanka Ringwald 170fcb08cdbSMilanka Ringwald static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){ 171fcb08cdbSMilanka Ringwald if (num_samples_to_write){ 172fcb08cdbSMilanka Ringwald const int num_samples = size - 3; 173fcb08cdbSMilanka Ringwald const int samples_to_write = btstack_min(num_samples, num_samples_to_write); 17482e01da0SMilanka Ringwald int8_t audio_frame_out[24]; 175379d044eSMilanka Ringwald 176*fbc7c9f2SMilanka Ringwald // memcpy(audio_frame_out, (int8_t*)(packet+3), 24); 177*fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_process_data(&cvsd_plc_state, (int8_t *)(packet+3), num_samples, audio_frame_out); 178379d044eSMilanka Ringwald 179*fbc7c9f2SMilanka Ringwald wav_writer_write_int8(samples_to_write, audio_frame_out); 180fcb08cdbSMilanka Ringwald num_samples_to_write -= samples_to_write; 181fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 182fcb08cdbSMilanka Ringwald sco_demo_close(); 183fcb08cdbSMilanka Ringwald } 184fcb08cdbSMilanka Ringwald dump_data = 0; 185fcb08cdbSMilanka Ringwald } 186fcb08cdbSMilanka Ringwald } 187fcb08cdbSMilanka Ringwald 1888b29cfc6SMatthias Ringwald #endif 1894a96141eSMatthias Ringwald #endif 1908b29cfc6SMatthias Ringwald 191fcb08cdbSMilanka Ringwald void sco_demo_close(void){ 192fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 19326463303SMilanka Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 194*fbc7c9f2SMilanka Ringwald wav_writer_close(); 19526463303SMilanka Ringwald printf("SCO demo statistics: "); 19626463303SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 19726463303SMilanka Ringwald printf("Used mSBC with PLC, number of processed frames: \n - %d good frames, \n - %d zero frames, \n - %d bad frames.", decoder_state.good_frames_nr, decoder_state.zero_frames_nr, decoder_state.bad_frames_nr); 19826463303SMilanka Ringwald } else { 19926463303SMilanka Ringwald printf("Used CVSD with PLC, number of proccesed frames: \n - %d good frames, \n - %d bad frames.", cvsd_plc_state.good_frames_nr, cvsd_plc_state.bad_frames_nr); 20026463303SMilanka Ringwald } 20126463303SMilanka Ringwald #endif 20226463303SMilanka Ringwald #endif 20326463303SMilanka Ringwald 20426463303SMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 205fcb08cdbSMilanka Ringwald #ifdef SCO_WAV_FILENAME 206fcb08cdbSMilanka Ringwald 207613518d1SMilanka Ringwald #if 0 208fcb08cdbSMilanka Ringwald printf("SCO Demo: closing wav file\n"); 209220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 2106e046a36SMatthias Ringwald wav_writer_state_t * writer_state = &wav_writer_state; 211fcb08cdbSMilanka Ringwald if (!writer_state->wav_file) return; 212fcb08cdbSMilanka Ringwald rewind(writer_state->wav_file); 2132afeea7fSMilanka Ringwald write_wav_header(writer_state->wav_file, writer_state->total_num_samples, btstack_sbc_decoder_num_channels(&decoder_state), btstack_sbc_decoder_sample_rate(&decoder_state),2); 214fcb08cdbSMilanka Ringwald fclose(writer_state->wav_file); 215fcb08cdbSMilanka Ringwald writer_state->wav_file = NULL; 216fcb08cdbSMilanka Ringwald } 217613518d1SMilanka Ringwald #endif 218fcb08cdbSMilanka Ringwald #endif 219fcb08cdbSMilanka Ringwald #endif 220fcb08cdbSMilanka Ringwald } 221fcb08cdbSMilanka Ringwald 222fcb08cdbSMilanka Ringwald void sco_demo_set_codec(uint8_t codec){ 223fcb08cdbSMilanka Ringwald if (negotiated_codec == codec) return; 224fcb08cdbSMilanka Ringwald negotiated_codec = codec; 225fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 22617cd946eSMatthias Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 227220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 228fcb08cdbSMilanka Ringwald sco_demo_init_mSBC(); 229fcb08cdbSMilanka Ringwald } else { 230fcb08cdbSMilanka Ringwald sco_demo_init_CVSD(); 231fcb08cdbSMilanka Ringwald } 232fcb08cdbSMilanka Ringwald #endif 233fcb08cdbSMilanka Ringwald #endif 234fcb08cdbSMilanka Ringwald } 235fcb08cdbSMilanka Ringwald 236f7c85330SMatthias Ringwald void sco_demo_init(void){ 237f7c85330SMatthias Ringwald 238f7c85330SMatthias Ringwald // status 239f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 240f7c85330SMatthias Ringwald #ifdef HAVE_PORTAUDIO 241f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, audio output via portaudio.\n"); 242f7c85330SMatthias Ringwald #else 243f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, hexdump received data.\n"); 244f7c85330SMatthias Ringwald #endif 245f7c85330SMatthias Ringwald #endif 246f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 247f7c85330SMatthias Ringwald printf("SCO Demo: Sending ASCII blocks, print received data.\n"); 248f7c85330SMatthias Ringwald #endif 249f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 250f7c85330SMatthias Ringwald printf("SCO Demo: Sending counter value, hexdump received data.\n"); 251f7c85330SMatthias Ringwald #endif 252f7c85330SMatthias Ringwald 253f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 254f7c85330SMatthias Ringwald int err; 255f7c85330SMatthias Ringwald PaStreamParameters outputParameters; 256f7c85330SMatthias Ringwald 257f7c85330SMatthias Ringwald /* -- initialize PortAudio -- */ 258f7c85330SMatthias Ringwald err = Pa_Initialize(); 259f7c85330SMatthias Ringwald if( err != paNoError ) return; 260f7c85330SMatthias Ringwald /* -- setup input and output -- */ 261f7c85330SMatthias Ringwald outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 262f7c85330SMatthias Ringwald outputParameters.channelCount = NUM_CHANNELS; 263f7c85330SMatthias Ringwald outputParameters.sampleFormat = PA_SAMPLE_TYPE; 264f7c85330SMatthias Ringwald outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 265f7c85330SMatthias Ringwald outputParameters.hostApiSpecificStreamInfo = NULL; 266f7c85330SMatthias Ringwald /* -- setup stream -- */ 267f7c85330SMatthias Ringwald err = Pa_OpenStream( 268f7c85330SMatthias Ringwald &stream, 269f7c85330SMatthias Ringwald NULL, // &inputParameters, 270f7c85330SMatthias Ringwald &outputParameters, 271f7c85330SMatthias Ringwald SAMPLE_RATE, 272f7c85330SMatthias Ringwald FRAMES_PER_BUFFER, 273f7c85330SMatthias Ringwald paClipOff, /* we won't output out of range samples so don't bother clipping them */ 274f7c85330SMatthias Ringwald NULL, /* no callback, use blocking API */ 275f7c85330SMatthias Ringwald NULL ); /* no callback, so no callback userData */ 276f7c85330SMatthias Ringwald if( err != paNoError ) return; 277f7c85330SMatthias Ringwald /* -- start stream -- */ 278f7c85330SMatthias Ringwald err = Pa_StartStream( stream ); 279f7c85330SMatthias Ringwald if( err != paNoError ) return; 280f7c85330SMatthias Ringwald #endif 281f7c85330SMatthias Ringwald 2827294d009SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_SINE 283f7c85330SMatthias Ringwald hci_set_sco_voice_setting(0x03); // linear, unsigned, 8-bit, transparent 2847294d009SMatthias Ringwald #endif 285f7c85330SMatthias Ringwald 286f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 287f7c85330SMatthias Ringwald phase = 'a'; 288f7c85330SMatthias Ringwald #endif 289f7c85330SMatthias Ringwald } 290f7c85330SMatthias Ringwald 2914a96141eSMatthias Ringwald static void sco_report(void){ 2924a96141eSMatthias Ringwald printf("SCO: sent %u, received %u\n", count_sent, count_received); 2934a96141eSMatthias Ringwald } 294f7c85330SMatthias Ringwald 295f7c85330SMatthias Ringwald void sco_demo_send(hci_con_handle_t sco_handle){ 296f7c85330SMatthias Ringwald 297f7c85330SMatthias Ringwald if (!sco_handle) return; 298f7c85330SMatthias Ringwald 299f7c85330SMatthias Ringwald const int sco_packet_length = 24 + 3; // hci_get_sco_packet_length(); 300f7c85330SMatthias Ringwald const int sco_payload_length = sco_packet_length - 3; 301f7c85330SMatthias Ringwald 302f7c85330SMatthias Ringwald hci_reserve_packet_buffer(); 303f7c85330SMatthias Ringwald uint8_t * sco_packet = hci_get_outgoing_packet_buffer(); 304f7c85330SMatthias Ringwald // set handle + flags 305f7c85330SMatthias Ringwald little_endian_store_16(sco_packet, 0, sco_handle); 306f7c85330SMatthias Ringwald // set len 307f7c85330SMatthias Ringwald sco_packet[2] = sco_payload_length; 308220eb563SMilanka Ringwald const int audio_samples_per_packet = sco_payload_length; // for 8-bit data. for 16-bit data it's /2 309f7c85330SMatthias Ringwald 310f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 311220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 312220eb563SMilanka Ringwald 313220eb563SMilanka Ringwald if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){ 314220eb563SMilanka Ringwald log_error("mSBC stream is empty."); 315220eb563SMilanka Ringwald } 316220eb563SMilanka Ringwald hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length); 317d5e5f834SMatthias Ringwald if (msbc_file_out){ 318d76591efSMatthias Ringwald // log outgoing mSBC data for testing 319d5e5f834SMatthias Ringwald fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out); 320d76591efSMatthias Ringwald } 3217294d009SMatthias Ringwald 322220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 323220eb563SMilanka Ringwald } else { 324*fbc7c9f2SMilanka Ringwald wav_synthesize_sine_wave_int8(audio_samples_per_packet, (int8_t *) (sco_packet+3)); 325220eb563SMilanka Ringwald } 326f7c85330SMatthias Ringwald #else 327f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 328220eb563SMilanka Ringwald memset(&sco_packet[3], phase++, audio_samples_per_packet); 329f7c85330SMatthias Ringwald if (phase > 'z') phase = 'a'; 330f7c85330SMatthias Ringwald #else 33138b2eaafSMatthias Ringwald int j; 332220eb563SMilanka Ringwald for (j=0;j<audio_samples_per_packet;j++){ 33338b2eaafSMatthias Ringwald sco_packet[3+j] = phase++; 334f7c85330SMatthias Ringwald } 335f7c85330SMatthias Ringwald #endif 336f7c85330SMatthias Ringwald #endif 337220eb563SMilanka Ringwald 338f7c85330SMatthias Ringwald hci_send_sco_packet_buffer(sco_packet_length); 339f7c85330SMatthias Ringwald 340f7c85330SMatthias Ringwald // request another send event 341f7c85330SMatthias Ringwald hci_request_sco_can_send_now_event(); 342f7c85330SMatthias Ringwald 3434a96141eSMatthias Ringwald count_sent++; 3444a96141eSMatthias Ringwald if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report(); 345f7c85330SMatthias Ringwald } 346f7c85330SMatthias Ringwald 347f7c85330SMatthias Ringwald /** 348f7c85330SMatthias Ringwald * @brief Process received data 349f7c85330SMatthias Ringwald */ 350f7c85330SMatthias Ringwald void sco_demo_receive(uint8_t * packet, uint16_t size){ 351f7c85330SMatthias Ringwald 352fcb08cdbSMilanka Ringwald dump_data = 1; 3538b29cfc6SMatthias Ringwald 3544a96141eSMatthias Ringwald count_received++; 3554a96141eSMatthias Ringwald // if ((count_received % SCO_REPORT_PERIOD) == 0) sco_report(); 3564a96141eSMatthias Ringwald 3574a96141eSMatthias Ringwald 3584a96141eSMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 3598b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 360220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 361fcb08cdbSMilanka Ringwald sco_demo_receive_mSBC(packet, size); 362fcb08cdbSMilanka Ringwald } else { 363fcb08cdbSMilanka Ringwald sco_demo_receive_CVSD(packet, size); 3648b29cfc6SMatthias Ringwald } 3658b29cfc6SMatthias Ringwald #endif 3664a96141eSMatthias Ringwald #endif 3678b29cfc6SMatthias Ringwald 368b3f76298SMilanka Ringwald if (packet[1] & 0x30){ 369b3f76298SMilanka Ringwald printf("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4); 370b3f76298SMilanka Ringwald log_info("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4); 371f7c85330SMatthias Ringwald printf_hexdump(&packet[3], size-3); 372b3f76298SMilanka Ringwald 373f7c85330SMatthias Ringwald return; 374f7c85330SMatthias Ringwald } 375f7c85330SMatthias Ringwald 376f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 377f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 378f7c85330SMatthias Ringwald uint32_t start = btstack_run_loop_get_time_ms(); 379f7c85330SMatthias Ringwald Pa_WriteStream( stream, &packet[3], size -3); 380f7c85330SMatthias Ringwald uint32_t end = btstack_run_loop_get_time_ms(); 381f7c85330SMatthias Ringwald if (end - start > 5){ 382f7c85330SMatthias Ringwald printf("Portaudio: write stream took %u ms\n", end - start); 383f7c85330SMatthias Ringwald } 3848b29cfc6SMatthias Ringwald dump_data = 0; 385f7c85330SMatthias Ringwald #endif 3868b29cfc6SMatthias Ringwald #endif 3878b29cfc6SMatthias Ringwald 3888b29cfc6SMatthias Ringwald if (dump_data){ 389f7c85330SMatthias Ringwald printf("data: "); 390f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 391f7c85330SMatthias Ringwald int i; 392f7c85330SMatthias Ringwald for (i=3;i<size;i++){ 393f7c85330SMatthias Ringwald printf("%c", packet[i]); 394f7c85330SMatthias Ringwald } 395f7c85330SMatthias Ringwald printf("\n"); 3968b29cfc6SMatthias Ringwald dump_data = 0; 3978b29cfc6SMatthias Ringwald #else 398f7c85330SMatthias Ringwald printf_hexdump(&packet[3], size-3); 399f7c85330SMatthias Ringwald #endif 4008b29cfc6SMatthias Ringwald } 401f7c85330SMatthias Ringwald } 402