Exemplo n.º 1
0
static int host_recv_pkt_cb(uint8_t *data, uint16_t len){

    if (xPortInIsrContext()){
        report_recv_called_from_isr();
        return 0;
    }

    xSemaphoreTake(ring_buffer_mutex, portMAX_DELAY);

    // check space
    uint16_t space = btstack_ring_buffer_bytes_free(&hci_ringbuffer);
    if (space < len){
        xSemaphoreGive(ring_buffer_mutex);
        log_error("transport_recv_pkt_cb packet %u, space %u -> dropping packet", len, space);
        return 0;
    }

    // store size in ringbuffer
    uint8_t len_tag[2];
    little_endian_store_16(len_tag, 0, len);
    btstack_ring_buffer_write(&hci_ringbuffer, len_tag, sizeof(len_tag));

    // store in ringbuffer
    btstack_ring_buffer_write(&hci_ringbuffer, data, len);

    xSemaphoreGive(ring_buffer_mutex);

    // set flag and trigger delivery of packets on main thread
    transport_packets_to_deliver = 1;
    btstack_run_loop_freertos_trigger();
    return 0;
}
Exemplo n.º 2
0
static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
    UNUSED(sample_rate);
    UNUSED(context);

#ifdef STORE_SBC_TO_WAV_FILE
    wav_writer_write_int16(num_samples*num_channels, data);
    frame_count++;
#endif

    total_num_samples+=num_samples*num_channels;

#ifdef HAVE_PORTAUDIO
    if (!pa_stream_started){
        /* -- start stream -- */
        PaError err = Pa_StartStream(stream);
        if (err != paNoError){
            printf("Error starting the stream: \"%s\"\n",  Pa_GetErrorText(err));
            return;
        }
        pa_stream_started = 1; 
        pa_stream_paused  = 1;
    }
    btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
#endif
}
Exemplo n.º 3
0
static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
    UNUSED(context);
    UNUSED(sample_rate);
    UNUSED(data);
    UNUSED(num_samples);
    UNUSED(num_channels);

#if (SCO_DEMO_MODE == SCO_DEMO_MODE_SINE) || (SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE)

    // printf("handle_pcm_data num samples %u, sample rate %d\n", num_samples, num_channels);
#ifdef HAVE_PORTAUDIO
    // samples in callback in host endianess, ready for PortAudio playback
    btstack_ring_buffer_write(&pa_output_ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
#endif /* HAVE_PORTAUDIO */

#ifdef SCO_WAV_FILENAME
    if (!num_samples_to_write) return;
    num_samples = btstack_min(num_samples, num_samples_to_write);
    num_samples_to_write -= num_samples;
    wav_writer_write_int16(num_samples, data);
    if (num_samples_to_write == 0){
        wav_writer_close();
    }
#endif /* SCO_WAV_FILENAME */

#endif /* Demo mode sine or microphone */
}
Exemplo n.º 4
0
static int portaudio_callback( const void *inputBuffer, void *outputBuffer,
                           unsigned long framesPerBuffer,
                           const PaStreamCallbackTimeInfo* timeInfo,
                           PaStreamCallbackFlags statusFlags,
                           void *userData ) {
    (void) timeInfo; /* Prevent unused variable warnings. */
    (void) statusFlags;
    (void) inputBuffer;
    (void) userData;
    
// output part

    // config based on codec
    int bytes_to_copy;
    uint32_t prebuffer_bytes;
    switch (negotiated_codec){
        case HFP_CODEC_MSBC:
            bytes_to_copy   = framesPerBuffer * MSBC_BYTES_PER_FRAME;
            prebuffer_bytes = MSBC_PA_PREBUFFER_BYTES;
            break;
        case HFP_CODEC_CVSD:
            bytes_to_copy   = framesPerBuffer * CVSD_BYTES_PER_FRAME;
            prebuffer_bytes = CVSD_PA_PREBUFFER_BYTES;
            break;
        default:
            bytes_to_copy   = framesPerBuffer * 2;  // assume 1 channel / 16 bit audio samples
            prebuffer_bytes = 0xfffffff;
            break;            
    }

    // fill with silence while paused
    if (pa_output_paused){
        if (btstack_ring_buffer_bytes_available(&pa_output_ring_buffer) < prebuffer_bytes){
            memset(outputBuffer, 0, bytes_to_copy);
            return 0;
        } else {
            // resume playback
            pa_output_paused = 0;
        }
    }

    // get data from ringbuffer
    uint32_t bytes_read = 0;
    btstack_ring_buffer_read(&pa_output_ring_buffer, outputBuffer, bytes_to_copy, &bytes_read);
    bytes_to_copy -= bytes_read;

    // fill with 0 if not enough
    if (bytes_to_copy){
        memset(outputBuffer + bytes_read, 0, bytes_to_copy);
        pa_output_paused = 1;
    }
// end of output part

// input part -- just store in ring buffer
#ifdef USE_PORTAUDIO_INPUT
    btstack_ring_buffer_write(&pa_input_ring_buffer, (uint8_t *)inputBuffer, framesPerBuffer * 2);
    pa_input_counter += framesPerBuffer * 2;
#endif
    return 0;
}
Exemplo n.º 5
0
static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
    UNUSED(sample_rate);
    UNUSED(context);

#ifdef STORE_SBC_TO_WAV_FILE
    wav_writer_write_int16(num_samples*num_channels, data);
    frame_count++;
#endif

#ifdef HAVE_PORTAUDIO
    // store pcm samples in ring buffer
    btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2);

    if (!audio_stream_started){
        audio_stream_paused  = 1;
        /* -- start stream -- */
        PaError err = Pa_StartStream(stream);
        if (err != paNoError){
            printf("Error starting the stream: \"%s\"\n",  Pa_GetErrorText(err));
            return;
        }
        audio_stream_started = 1; 
    }
#endif

#ifdef HAVE_AUDIO_DMA
    // store in ring buffer
    uint8_t * write_data = start_of_buffer(write_buffer);
    uint16_t len = num_samples*num_channels*2;
    memcpy(write_data, data, len);
    audio_samples_len[write_buffer] = len;

    // add/drop audio frame to fix drift
    if (sbc_samples_fix > 0){
        memcpy(write_data + len, write_data + len - 4, 4);
        audio_samples_len[write_buffer] += 4;
    }
    if (sbc_samples_fix < 0){
        audio_samples_len[write_buffer] -= 4;
    }

    write_buffer = next_buffer(write_buffer);
#endif
}
Exemplo n.º 6
0
static void fill_ring_buffer(void *userData){
    paTestData *data = (paTestData*)userData;

    while (btstack_ring_buffer_bytes_free(&ring_buffer) > BYTES_PER_FRAME){
        uint8_t write_data[BYTES_PER_FRAME];
        *(int16_t*)&write_data[0] = data->sine[data->left_phase];
        *(int16_t*)&write_data[2] = data->sine[data->right_phase];
        
        btstack_ring_buffer_write(&ring_buffer, write_data, BYTES_PER_FRAME);
        write_wav_data((int16_t*)write_data, 1, NUM_CHANNELS, SAMPLE_RATE);

        data->left_phase += 1;
        if (data->left_phase >= TABLE_SIZE){
            data->left_phase -= TABLE_SIZE;
        }
        data->right_phase += 2; /* higher pitch so we can distinguish left and right. */
        if (data->right_phase >= TABLE_SIZE){
            data->right_phase -= TABLE_SIZE;
        } 
    }
}
Exemplo n.º 7
0
static void handle_l2cap_media_data_packet(uint8_t seid, uint8_t *packet, uint16_t size){
    UNUSED(seid);
    int pos = 0;
    
    avdtp_media_packet_header_t media_header;
    if (!read_media_data_header(packet, size, &pos, &media_header)) return;
    
    avdtp_sbc_codec_header_t sbc_header;
    if (!read_sbc_header(packet, size, &pos, &sbc_header)) return;

#ifdef HAVE_AUDIO_DMA
    // store sbc frame size for buffer management
    sbc_frame_size = (size-pos)/ sbc_header.num_frames;
#endif
    
#if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE)
    btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos);
#endif

#ifdef HAVE_AUDIO_DMA
    btstack_ring_buffer_write(&ring_buffer,  packet+pos, size-pos);

    // decide on audio sync drift based on number of sbc frames in queue
    int sbc_frames_in_buffer = btstack_ring_buffer_bytes_available(&ring_buffer) / sbc_frame_size;
    if (sbc_frames_in_buffer < OPTIMAL_FRAMES_MIN){
        sbc_samples_fix = 1;    // duplicate last sample
    } else if (sbc_frames_in_buffer <= OPTIMAL_FRAMES_MAX){
        sbc_samples_fix = 0;    // nothing to do
    } else {
        sbc_samples_fix = -1;   // drop last sample
    }

    // dump
    printf("%6u %03u %d\n",  (int) btstack_run_loop_get_time_ms(), sbc_frames_in_buffer, sbc_samples_fix);
#endif

#ifdef STORE_SBC_TO_SBC_FILE
    fwrite(packet+pos, size-pos, 1, sbc_file);
#endif
}
Exemplo n.º 8
0
static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){
    if (!num_samples_to_write) return;

    int16_t audio_frame_out[128];    // 

    if (size > sizeof(audio_frame_out)){
        printf("sco_demo_receive_CVSD: SCO packet larger than local output buffer - dropping data.\n");
        return;
    }

#if defined(SCO_WAV_FILENAME) || defined(USE_PORTAUDIO)
    const int audio_bytes_read = size - 3;
    const int num_samples = audio_bytes_read / CVSD_BYTES_PER_FRAME;

    // convert into host endian
    int16_t audio_frame_in[128];
    int i;
    for (i=0;i<num_samples;i++){
        audio_frame_in[i] = little_endian_read_16(packet, 3 + i * 2);
    }

    btstack_cvsd_plc_process_data(&cvsd_plc_state, audio_frame_in, num_samples, audio_frame_out);
#endif

#ifdef SCO_WAV_FILENAME
    // Samples in CVSD SCO packet are in little endian, ready for wav files (take shortcut)
    const int samples_to_write = btstack_min(num_samples, num_samples_to_write);
    wav_writer_write_le_int16(samples_to_write, audio_frame_out);
    num_samples_to_write -= samples_to_write;
    if (num_samples_to_write == 0){
        wav_writer_close();
    }
#endif

#ifdef USE_PORTAUDIO
    btstack_ring_buffer_write(&pa_output_ring_buffer, (uint8_t *)audio_frame_out, audio_bytes_read);
#endif
}