Example #1
0
void sco_demo_send(hci_con_handle_t sco_handle){

    if (!sco_handle) return;
    
    const int sco_packet_length = 24 + 3; // hci_get_sco_packet_length();
    const int sco_payload_length = sco_packet_length - 3;

    hci_reserve_packet_buffer();
    uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
    // set handle + flags
    little_endian_store_16(sco_packet, 0, sco_handle);
    // set len
    sco_packet[2] = sco_payload_length;
    const int frames_per_packet = sco_payload_length;    // for 8-bit data. for 16-bit data it's /2

#if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
    int i;
    for (i=0;i<frames_per_packet;i++){
        sco_packet[3+i] = sine[phase];
        phase++;
        if (phase >= sizeof(sine)) phase = 0;
    }
#else
#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
    memset(&sco_packet[3], phase++, frames_per_packet);
    if (phase > 'z') phase = 'a';
#else
    int j;
    for (j=0;j<frames_per_packet;j++){
        sco_packet[3+j] = phase++;
    }
#endif
#endif
    hci_send_sco_packet_buffer(sco_packet_length);

    // request another send event
    hci_request_sco_can_send_now_event();

    count_sent++;
    if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report();
}
Example #2
0
void sco_demo_send(hci_con_handle_t sco_handle){

    if (!sco_handle) return;
    
    int sco_packet_length = hci_get_sco_packet_length();
    int sco_payload_length = sco_packet_length - 3;

    hci_reserve_packet_buffer();
    uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
#if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
#ifdef ENABLE_HFP_WIDE_BAND_SPEECH
    if (negotiated_codec == HFP_CODEC_MSBC){
        // overwrite
        sco_payload_length = 24;
        sco_packet_length = sco_payload_length + 3;

        if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){
            log_error("mSBC stream is empty.");
        }
        hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length);
        if (msbc_file_out){
            // log outgoing mSBC data for testing
            fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out);
        }

        sco_demo_msbc_fill_sine_audio_frame();
    } else
#endif
    {
        const int audio_samples_per_packet = sco_payload_length / CVSD_BYTES_PER_FRAME;  
        sco_demo_sine_wave_int16_at_8000_hz_little_endian(audio_samples_per_packet, &sco_packet[3]);
    }
#endif

#if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE

#ifdef HAVE_PORTAUDIO
    if (negotiated_codec == HFP_CODEC_MSBC){
        // MSBC

        // overwrite
        sco_payload_length = 24;
        sco_packet_length = sco_payload_length + 3;

        if (pa_input_paused){
            if (btstack_ring_buffer_bytes_available(&pa_input_ring_buffer) >= MSBC_PA_PREBUFFER_BYTES){
                // resume sending
                pa_input_paused = 0;
            }
        }

        if (!pa_input_paused){
            int num_samples = hfp_msbc_num_audio_samples_per_frame();
            if (hfp_msbc_can_encode_audio_frame_now() && btstack_ring_buffer_bytes_available(&pa_input_ring_buffer) >= (num_samples * MSBC_BYTES_PER_FRAME)){
                int16_t sample_buffer[num_samples];
                uint32_t bytes_read;
                btstack_ring_buffer_read(&pa_input_ring_buffer, (uint8_t*) sample_buffer, num_samples * MSBC_BYTES_PER_FRAME, &bytes_read);
                hfp_msbc_encode_audio_frame(sample_buffer);
                num_audio_frames++;
            }
        }

        if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){
            log_error("mSBC stream should not be empty.");
            memset(sco_packet + 3, 0, sco_payload_length);
            pa_input_paused = 1;
        } else {
            hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length);
            if (msbc_file_out){
                // log outgoing mSBC data for testing
                fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out);
            }
        }

    } else {
        // CVSD

        log_info("send: bytes avail %u, free %u, counter %u", btstack_ring_buffer_bytes_available(&pa_input_ring_buffer), btstack_ring_buffer_bytes_free(&pa_input_ring_buffer), pa_input_counter);
        // fill with silence while paused
        int bytes_to_copy = sco_payload_length;
        if (pa_input_paused){
            if (btstack_ring_buffer_bytes_available(&pa_input_ring_buffer) >= CVSD_PA_PREBUFFER_BYTES){
                // resume sending
                pa_input_paused = 0;
            }
        }

        // get data from ringbuffer
        uint16_t pos = 0;
        uint8_t * sample_data = &sco_packet[3];
        if (!pa_input_paused){
            uint32_t bytes_read = 0;
            btstack_ring_buffer_read(&pa_input_ring_buffer, sample_data, bytes_to_copy, &bytes_read);
            // flip 16 on big endian systems
            // @note We don't use (uint16_t *) casts since all sample addresses are odd which causes crahses on some systems
            if (btstack_is_big_endian()){
                int i;
                for (i=0;i<bytes_read;i+=2){
                    uint8_t tmp        = sample_data[i*2];
                    sample_data[i*2]   = sample_data[i*2+1];
                    sample_data[i*2+1] = tmp;
                }
            }
            bytes_to_copy -= bytes_read;
            pos           += bytes_read;
        }

        // fill with 0 if not enough
        if (bytes_to_copy){
            memset(sample_data + pos, 0, bytes_to_copy);
            pa_input_paused = 1;
        }
    }
#else
    // just send '0's
    if (negotiated_codec == HFP_CODEC_MSBC){
        sco_payload_length = 24;
        sco_packet_length = sco_payload_length + 3;
    }
    memset(sco_packet + 3, 0, sco_payload_length);
#endif
#endif

#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
    memset(&sco_packet[3], phase++, sco_payload_length);
    if (phase > 'z') phase = 'a';
#endif
#if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER
    int j;
    for (j=0;j<sco_payload_length;j++){
        sco_packet[3+j] = phase++;
    }
#endif
#if SCO_DEMO_MODE == SCO_DEMO_MODE_55
    int j;
    for (j=0;j<sco_payload_length;j++){
        // sco_packet[3+j] = j & 1 ? 0x35 : 0x53;
        sco_packet[3+j] = 0x55;
    }
#endif
#if SCO_DEMO_MODE == SCO_DEMO_MODE_00
    int j;
    for (j=0;j<sco_payload_length;j++){
        sco_packet[3+j] = 0x00;
    }
    // additional hack
    // big_endian_store_16(sco_packet, 5, phase++);
    (void) phase;
#endif

    // test silence
    // memset(sco_packet+3, 0, sco_payload_length);

    // set handle + flags
    little_endian_store_16(sco_packet, 0, sco_handle);
    // set len
    sco_packet[2] = sco_payload_length;
    // finally send packet 
    hci_send_sco_packet_buffer(sco_packet_length);

    // request another send event
    hci_request_sco_can_send_now_event();

    count_sent++;
#if SCO_DEMO_MODE != SCO_DEMO_MODE_55
    if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report();
#endif
}