mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-16 08:42:28 +00:00
introduce portaudio in avdtp_sink
This commit is contained in:
parent
b07c2f619d
commit
2af9447338
@ -71,7 +71,7 @@ SBC_ENCODER_OBJ = $(SBC_ENCODER:.c=.o)
|
|||||||
|
|
||||||
all: ${AVDTP_TESTS}
|
all: ${AVDTP_TESTS}
|
||||||
|
|
||||||
avdtp_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} avdtp_sink.o avdtp_test.o
|
avdtp_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} btstack_ring_buffer.o avdtp_sink.o avdtp_test.o
|
||||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||||
|
|
||||||
portaudio_test: btstack_util.o hci_dump.o wav_util.o btstack_ring_buffer.o portaudio_test.c
|
portaudio_test: btstack_util.o hci_dump.o wav_util.o btstack_ring_buffer.o portaudio_test.c
|
||||||
|
@ -49,8 +49,88 @@
|
|||||||
#include "btstack_sbc.h"
|
#include "btstack_sbc.h"
|
||||||
#include "wav_util.h"
|
#include "wav_util.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_PORTAUDIO
|
||||||
|
#include <portaudio.h>
|
||||||
|
#include "btstack_ring_buffer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUM_CHANNELS 2
|
||||||
|
#define SAMPLE_RATE 44100
|
||||||
|
|
||||||
|
#ifdef HAVE_POSIX_FILE_IO
|
||||||
#define STORE_SBC_TO_SBC_FILE
|
#define STORE_SBC_TO_SBC_FILE
|
||||||
#define STORE_SBC_TO_WAV_FILE
|
#define STORE_SBC_TO_WAV_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PORTAUDIO
|
||||||
|
#define PA_SAMPLE_TYPE paInt16
|
||||||
|
#define FRAMES_PER_BUFFER 128
|
||||||
|
#define BYTES_PER_FRAME (2*NUM_CHANNELS)
|
||||||
|
#define PREBUFFER_MS 150
|
||||||
|
#define PREBUFFER_BYTES (PREBUFFER_MS*SAMPLE_RATE/1000*BYTES_PER_FRAME)
|
||||||
|
static uint8_t ring_buffer_storage[2*PREBUFFER_BYTES];
|
||||||
|
static btstack_ring_buffer_t ring_buffer;
|
||||||
|
|
||||||
|
static PaStream * stream;
|
||||||
|
static uint8_t pa_stream_started = 0;
|
||||||
|
|
||||||
|
static int patestCallback( 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;
|
||||||
|
|
||||||
|
uint16_t bytes_read = 0;
|
||||||
|
int bytes_per_buffer = framesPerBuffer * BYTES_PER_FRAME;
|
||||||
|
|
||||||
|
if (btstack_ring_buffer_bytes_available(&ring_buffer) >= bytes_per_buffer){
|
||||||
|
btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_per_buffer, &bytes_read);
|
||||||
|
} else {
|
||||||
|
printf("NOT ENOUGH DATA!\n");
|
||||||
|
memset(outputBuffer, 0, bytes_per_buffer);
|
||||||
|
}
|
||||||
|
printf("bytes avail after read: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STORE_SBC_TO_WAV_FILE
|
||||||
|
// store sbc as wav:
|
||||||
|
static btstack_sbc_decoder_state_t state;
|
||||||
|
static int total_num_samples = 0;
|
||||||
|
static int frame_count = 0;
|
||||||
|
static char * wav_filename = "avdtp_sink.wav";
|
||||||
|
static btstack_sbc_mode_t mode = SBC_MODE_STANDARD;
|
||||||
|
|
||||||
|
static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
|
||||||
|
wav_writer_write_int16(num_samples*num_channels, data);
|
||||||
|
total_num_samples+=num_samples*num_channels;
|
||||||
|
frame_count++;
|
||||||
|
|
||||||
|
#ifdef HAVE_PORTAUDIO
|
||||||
|
if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= PREBUFFER_BYTES){
|
||||||
|
/* -- 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;
|
||||||
|
}
|
||||||
|
btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
|
||||||
|
printf("bytes avail after write: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STORE_SBC_TO_SBC_FILE
|
||||||
|
static FILE * sbc_file;
|
||||||
|
static char * sbc_filename = "avdtp_sink.sbc";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static const char * default_avdtp_sink_service_name = "BTstack AVDTP Sink Service";
|
static const char * default_avdtp_sink_service_name = "BTstack AVDTP Sink Service";
|
||||||
static const char * default_avdtp_sink_service_provider_name = "BTstack AVDTP Sink Service Provider";
|
static const char * default_avdtp_sink_service_provider_name = "BTstack AVDTP Sink Service Provider";
|
||||||
@ -64,24 +144,6 @@ static btstack_packet_handler_t avdtp_sink_callback;
|
|||||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||||
static void avdtp_sink_run_for_connection(avdtp_sink_connection_t *connection);
|
static void avdtp_sink_run_for_connection(avdtp_sink_connection_t *connection);
|
||||||
|
|
||||||
#ifdef STORE_SBC_TO_WAV_FILE
|
|
||||||
// store sbc as wav:
|
|
||||||
static btstack_sbc_decoder_state_t state;
|
|
||||||
static int total_num_samples = 0;
|
|
||||||
static int frame_count = 0;
|
|
||||||
static char * wav_filename = "avdtp_sink.wav";
|
|
||||||
static btstack_sbc_mode_t mode = SBC_MODE_STANDARD;
|
|
||||||
static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
|
|
||||||
wav_writer_write_int16(num_samples, data);
|
|
||||||
total_num_samples+=num_samples;
|
|
||||||
frame_count++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef STORE_SBC_TO_SBC_FILE
|
|
||||||
static FILE * sbc_file;
|
|
||||||
static char * sbc_filename = "avdtp_sink.sbc";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){
|
void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){
|
||||||
uint8_t* attribute;
|
uint8_t* attribute;
|
||||||
@ -519,11 +581,11 @@ static void handle_l2cap_media_data_packet(avdtp_sink_connection_t * connection,
|
|||||||
|
|
||||||
// TODO: read csrc list
|
// TODO: read csrc list
|
||||||
|
|
||||||
printf_hexdump( packet, pos );
|
// printf_hexdump( packet, pos );
|
||||||
printf("MEDIA HEADER: %u timestamp, version %u, padding %u, extension %u, csrc_count %u\n",
|
// printf("MEDIA HEADER: %u timestamp, version %u, padding %u, extension %u, csrc_count %u\n",
|
||||||
media_header.timestamp, media_header.version, media_header.padding, media_header.extension, media_header.csrc_count);
|
// media_header.timestamp, media_header.version, media_header.padding, media_header.extension, media_header.csrc_count);
|
||||||
printf("MEDIA HEADER: marker %02x, payload_type %02x, sequence_number %u, synchronization_source %u\n",
|
// printf("MEDIA HEADER: marker %02x, payload_type %02x, sequence_number %u, synchronization_source %u\n",
|
||||||
media_header.marker, media_header.payload_type, media_header.sequence_number, media_header.synchronization_source);
|
// media_header.marker, media_header.payload_type, media_header.sequence_number, media_header.synchronization_source);
|
||||||
|
|
||||||
avdtp_sbc_codec_header_t sbc_header;
|
avdtp_sbc_codec_header_t sbc_header;
|
||||||
sbc_header.fragmentation = get_bit16(packet[pos], 7);
|
sbc_header.fragmentation = get_bit16(packet[pos], 7);
|
||||||
@ -532,8 +594,8 @@ static void handle_l2cap_media_data_packet(avdtp_sink_connection_t * connection,
|
|||||||
sbc_header.num_frames = packet[pos] & 0x0f;
|
sbc_header.num_frames = packet[pos] & 0x0f;
|
||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
printf("SBC HEADER: num_frames %u, fragmented %u, start %u, stop %u\n", sbc_header.num_frames, sbc_header.fragmentation, sbc_header.starting_packet, sbc_header.last_packet);
|
// printf("SBC HEADER: num_frames %u, fragmented %u, start %u, stop %u\n", sbc_header.num_frames, sbc_header.fragmentation, sbc_header.starting_packet, sbc_header.last_packet);
|
||||||
printf_hexdump( packet+pos, size-pos );
|
// printf_hexdump( packet+pos, size-pos );
|
||||||
#ifdef STORE_SBC_TO_WAV_FILE
|
#ifdef STORE_SBC_TO_WAV_FILE
|
||||||
btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos);
|
btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos);
|
||||||
#endif
|
#endif
|
||||||
@ -541,7 +603,6 @@ static void handle_l2cap_media_data_packet(avdtp_sink_connection_t * connection,
|
|||||||
#ifdef STORE_SBC_TO_SBC_FILE
|
#ifdef STORE_SBC_TO_SBC_FILE
|
||||||
fwrite(packet+pos, size-pos, 1, sbc_file);
|
fwrite(packet+pos, size-pos, 1, sbc_file);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_l2cap_signaling_data_packet(avdtp_sink_connection_t * connection, uint8_t *packet, uint16_t size){
|
static void handle_l2cap_signaling_data_packet(avdtp_sink_connection_t * connection, uint8_t *packet, uint16_t size){
|
||||||
@ -614,7 +675,7 @@ static void handle_l2cap_signaling_data_packet(avdtp_sink_connection_t * connect
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:{
|
||||||
printf("NOT IMPLEMENTED signal_identifier %d\n", signaling_header.signal_identifier);
|
printf("NOT IMPLEMENTED signal_identifier %d\n", signaling_header.signal_identifier);
|
||||||
printf_hexdump( packet, size );
|
printf_hexdump( packet, size );
|
||||||
#ifdef STORE_SBC_TO_WAV_FILE
|
#ifdef STORE_SBC_TO_WAV_FILE
|
||||||
@ -628,7 +689,28 @@ static void handle_l2cap_signaling_data_packet(avdtp_sink_connection_t * connect
|
|||||||
#ifdef STORE_SBC_TO_SBC_FILE
|
#ifdef STORE_SBC_TO_SBC_FILE
|
||||||
fclose(sbc_file);
|
fclose(sbc_file);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PORTAUDIO
|
||||||
|
PaError err = Pa_StopStream(stream);
|
||||||
|
if (err != paNoError){
|
||||||
|
printf("Error stopping the stream: \"%s\"\n", Pa_GetErrorText(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pa_stream_started = 0;
|
||||||
|
err = Pa_CloseStream(stream);
|
||||||
|
if (err != paNoError){
|
||||||
|
printf("Error closing the stream: \"%s\"\n", Pa_GetErrorText(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Pa_Terminate();
|
||||||
|
if (err != paNoError){
|
||||||
|
printf("Error terminating portaudio: \"%s\"\n", Pa_GetErrorText(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -810,15 +892,49 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
|||||||
// TODO: find out which security level is needed, and replace LEVEL_0 in avdtp_sink_init
|
// TODO: find out which security level is needed, and replace LEVEL_0 in avdtp_sink_init
|
||||||
void avdtp_sink_init(void){
|
void avdtp_sink_init(void){
|
||||||
#ifdef STORE_SBC_TO_WAV_FILE
|
#ifdef STORE_SBC_TO_WAV_FILE
|
||||||
int num_channels = 2;
|
btstack_sbc_decoder_init(&state, mode, &handle_pcm_data, NULL);
|
||||||
btstack_sbc_decoder_init(&state, mode, num_channels, &handle_pcm_data, NULL);
|
wav_writer_open(wav_filename, NUM_CHANNELS, SAMPLE_RATE);
|
||||||
wav_writer_open(wav_filename, num_channels, 44100);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef STORE_SBC_TO_SBC_FILE
|
#ifdef STORE_SBC_TO_SBC_FILE
|
||||||
sbc_file = fopen(sbc_filename, "wb");
|
sbc_file = fopen(sbc_filename, "wb");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PORTAUDIO
|
||||||
|
PaError err;
|
||||||
|
PaStreamParameters outputParameters;
|
||||||
|
|
||||||
|
/* -- initialize PortAudio -- */
|
||||||
|
err = Pa_Initialize();
|
||||||
|
if (err != paNoError){
|
||||||
|
printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* -- setup input and output -- */
|
||||||
|
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||||
|
outputParameters.channelCount = NUM_CHANNELS;
|
||||||
|
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||||
|
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
|
||||||
|
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||||
|
/* -- setup stream -- */
|
||||||
|
err = Pa_OpenStream(
|
||||||
|
&stream,
|
||||||
|
NULL, /* &inputParameters */
|
||||||
|
&outputParameters,
|
||||||
|
SAMPLE_RATE,
|
||||||
|
FRAMES_PER_BUFFER,
|
||||||
|
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||||
|
patestCallback, /* use callback */
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if (err != paNoError){
|
||||||
|
printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage));
|
||||||
|
btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage));
|
||||||
|
pa_stream_started = 0;
|
||||||
|
#endif
|
||||||
l2cap_register_service(&packet_handler, PSM_AVDTP, 0xffff, LEVEL_0);
|
l2cap_register_service(&packet_handler, PSM_AVDTP, 0xffff, LEVEL_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +58,9 @@
|
|||||||
#define TABLE_SIZE 100
|
#define TABLE_SIZE 100
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float sine[TABLE_SIZE];
|
int16_t sine[TABLE_SIZE];
|
||||||
int left_phase;
|
int left_phase;
|
||||||
int right_phase;
|
int right_phase;
|
||||||
char message[20];
|
|
||||||
} paTestData;
|
} paTestData;
|
||||||
|
|
||||||
static uint8_t ring_buffer_storage[3*FRAMES_PER_BUFFER*BYTES_PER_FRAME];
|
static uint8_t ring_buffer_storage[3*FRAMES_PER_BUFFER*BYTES_PER_FRAME];
|
||||||
@ -76,17 +75,14 @@ static void write_wav_data(int16_t * data, int num_frames, int num_channels, int
|
|||||||
if (total_num_samples>5*SAMPLE_RATE) wav_writer_close();
|
if (total_num_samples>5*SAMPLE_RATE) wav_writer_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void fill_ring_buffer(void *userData){
|
static void fill_ring_buffer(void *userData){
|
||||||
paTestData *data = (paTestData*)userData;
|
paTestData *data = (paTestData*)userData;
|
||||||
|
|
||||||
while (btstack_ring_buffer_bytes_free(&ring_buffer) > BYTES_PER_FRAME){
|
while (btstack_ring_buffer_bytes_free(&ring_buffer) > BYTES_PER_FRAME){
|
||||||
int16_t left = data->sine[data->left_phase] * 32767;
|
|
||||||
int16_t right = data->sine[data->right_phase] * 32767;
|
|
||||||
|
|
||||||
uint8_t write_data[BYTES_PER_FRAME];
|
uint8_t write_data[BYTES_PER_FRAME];
|
||||||
*(int16_t*)&write_data[0] = left;
|
*(int16_t*)&write_data[0] = data->sine[data->left_phase];
|
||||||
*(int16_t*)&write_data[2] = right;
|
*(int16_t*)&write_data[2] = data->sine[data->right_phase];
|
||||||
|
|
||||||
btstack_ring_buffer_write(&ring_buffer, write_data, BYTES_PER_FRAME);
|
btstack_ring_buffer_write(&ring_buffer, write_data, BYTES_PER_FRAME);
|
||||||
write_wav_data((int16_t*)write_data, 1, NUM_CHANNELS, SAMPLE_RATE);
|
write_wav_data((int16_t*)write_data, 1, NUM_CHANNELS, SAMPLE_RATE);
|
||||||
|
|
||||||
@ -116,7 +112,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
|||||||
if (btstack_ring_buffer_bytes_available(&ring_buffer) >= bytes_per_buffer){
|
if (btstack_ring_buffer_bytes_available(&ring_buffer) >= bytes_per_buffer){
|
||||||
btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_per_buffer, &bytes_read);
|
btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_per_buffer, &bytes_read);
|
||||||
} else {
|
} else {
|
||||||
printf("NOT ENGOUGH DAT!\n");
|
printf("NOT ENOUGH DATA!\n");
|
||||||
memset(outputBuffer, 0, bytes_per_buffer);
|
memset(outputBuffer, 0, bytes_per_buffer);
|
||||||
}
|
}
|
||||||
return paContinue;
|
return paContinue;
|
||||||
@ -124,7 +120,6 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
|||||||
|
|
||||||
|
|
||||||
int main(int argc, const char * argv[]){
|
int main(int argc, const char * argv[]){
|
||||||
|
|
||||||
PaError err;
|
PaError err;
|
||||||
static paTestData data;
|
static paTestData data;
|
||||||
static PaStream * stream;
|
static PaStream * stream;
|
||||||
@ -132,7 +127,7 @@ int main(int argc, const char * argv[]){
|
|||||||
/* initialise sinusoidal wavetable */
|
/* initialise sinusoidal wavetable */
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<TABLE_SIZE; i++){
|
for (i=0; i<TABLE_SIZE; i++){
|
||||||
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
data.sine[i] = sin(((double)i/(double)TABLE_SIZE) * M_PI * 2.)*32767;
|
||||||
}
|
}
|
||||||
data.left_phase = data.right_phase = 0;
|
data.left_phase = data.right_phase = 0;
|
||||||
|
|
||||||
@ -143,13 +138,12 @@ int main(int argc, const char * argv[]){
|
|||||||
}
|
}
|
||||||
|
|
||||||
PaStreamParameters outputParameters;
|
PaStreamParameters outputParameters;
|
||||||
|
|
||||||
/* -- setup input and output -- */
|
|
||||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||||
outputParameters.channelCount = NUM_CHANNELS;
|
outputParameters.channelCount = NUM_CHANNELS;
|
||||||
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
|
||||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
|
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
|
||||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||||
|
|
||||||
/* -- setup stream -- */
|
/* -- setup stream -- */
|
||||||
err = Pa_OpenStream(
|
err = Pa_OpenStream(
|
||||||
&stream,
|
&stream,
|
||||||
@ -159,7 +153,7 @@ int main(int argc, const char * argv[]){
|
|||||||
FRAMES_PER_BUFFER,
|
FRAMES_PER_BUFFER,
|
||||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||||
patestCallback, /* use callback */
|
patestCallback, /* use callback */
|
||||||
&data ); /* no callback userData yet */
|
&data ); /* callback userData */
|
||||||
|
|
||||||
memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage));
|
memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage));
|
||||||
btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage));
|
btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user