Hi
Did you test other resample methods? There are quite a few available
and "trivial" is definitely the worst of them.
Although it maybe depend on CPU, Is there any recommend setting for
resampling-method?
Could you tell me a character for each parameters in resampling-method?
> Sorry, currently I have no idea what goes wrong. The number of 96 bytes /
> 10ms
> sounds weird and does not match any of the involved sample rates / formats.
> Is your code available somewhere so that I can take a look?
>
I attached source code to control pulseaudio.Could you take a look my code?
start function
usbbtf_hs_start()
read callback
usbbtf_hs_stream_read_cb()
I got 96bytes voice data as a parameter of usbbtf_hs_stream_read_cb().
So I didn't have a clue to find any hint on this code.
Is there any sample code for implement to control pulseaudio?
Is it possibly code for parec and another command for pulseaudio?
I refered to Linux Sound Programming.
Best Regards,
Shinnosuke Suzuki
2018-02-11 6:12 GMT+09:00 Georg Chini <[email protected]>:
> On 10.02.2018 02:11, Shinnosuke Suzuki wrote:
>
> Hi
>
> PA 11.1 should work fine with your kernel and bluez version.
>
>
> Thank you, I’ll try that.
>
> When you record from the BT headset, the BT headset is set to HSP/HFP.
> This means that recording and playback stream are at 8kHz, not 16kHz.
>
>
> I want to handle voice packet as Linear 16bit little endian 16000Hz,
> I configure stream as follows.
>
> static pa_sample_spec samplespec = {
> .format = PA_SAMPLE_S16LE, /* Linear 16bit */
> .rate = 16000, /* 16000Hz */
> .channels = 1 /* mono */
> }
>
> Does it means .rate should be 8000?
>
>
> It should work if you specify 16kHz because PA will do the resampling.
> But I would try with 8kHz, just to see if something changes.
> Did you try another source? Does parecord work with your headset?
>
>
> You should not expect to get a fixed number of bytes in a fixed time
> interval. This is only true on average but not for a single callback. Are
> the 96 bytes an average value?
> If your application needs constant size data packets, you may have to
> buffer some data.
> Did you take a look at the pacat code to see how reading data from
> a stream is done correctly?
>
>
> I don’t expect fixed number of bytes. So, I implemented to buffer voice
> packets in read callback.
> However I got voice packet on my callback at 96 bytes per 10ms constantly.
> It means I couldn’t get sufficient voice packet because voice packet needs
> at least 320bytes per 10ms in case of Linear 16bit little endian 16000Hz.
>
> I read pacat how to handle voice packet in read callback.
> I implemented like pacat except silence hole using pa_silence_memory().
>
>
> Sorry, currently I have no idea what goes wrong. The number of 96 bytes /
> 10ms
> sounds weird and does not match any of the involved sample rates / formats.
> Is your code available somewhere so that I can take a look?
>
--
--
Shinnosuke Suzuki
E-mail : [email protected]
#include <stdio.h>
#include <string.h>
#include <pulse/pulseaudio.h>
#include <unistd.h>
/* Protottype definition */
void usbbtf_hs_stream_read_cb (pa_stream *s, size_t length, void *userdata);
void usbbtf_hs_stream_state_cb_record (pa_stream *s, void *userdata);
void usbbtf_hs_stream_state_cb_playback (pa_stream *s, void *userdata);
void usbbtf_hs_context_state_cb (pa_context *c, void *userdata);
int usbbtf_hs_stream_write (void *data, int length);
/* Global Table */
extern struct usbbt_task_tbl u_task_tbl;
static pa_sample_spec sample_spec = {
.format = PA_SAMPLE_S16LE, /* Linear 16bit Little Endian */
.rate = 16000, /* 16kHz */
.channels = 1 /* mono */
};
static pa_stream_flags_t flags = 0;
static pa_stream *istream = NULL,
*ostream = NULL;
#define USBBT_DSP_MEDIA_PACKET_SIZE 320
static char hs_media_buff[USBBT_DSP_MEDIA_PACKET_SIZE];
static int buff_pos = 0;
extern void mcf_DecodeMedia(char*data,int len);
extern int usbbt_conn_mode;
/************************************************************************
************************************************************************/
void usbbtf_hs_stream_read_cb (pa_stream *s, size_t length, void *userdata){
const void *data;
size_t len;
int diff_len = 0;
struct timespec log_time;
printf("PA_r len:%d\n", length);
while (pa_stream_readable_size(s) > 0) {
if (pa_stream_peek(s, &data, &len) < 0) {
printf("Read failed\n");
return;
}
memset(&log_time, 0, sizeof(log_time));
clock_gettime(CLOCK_REALTIME, &log_time);
printf("HSET_r <- PA len: %d %ld %s", len, log_time.tv_nsec, ctime(&log_time.tv_sec));
if((buff_pos + len) >= USBBT_DSP_MEDIA_PACKET_SIZE){
diff_len = USBBT_DSP_MEDIA_PACKET_SIZE - buff_pos;
memcpy(hs_media_buff + buff_pos, data, diff_len);
/* send dsp */
mcf_DecodeMedia(hs_media_buff, USBBT_DSP_MEDIA_PACKET_SIZE);
memset(hs_media_buff, 0, sizeof(hs_media_buff));
memcpy(hs_media_buff, data + diff_len, len - diff_len);
buff_pos = len - diff_len;
} else {
memcpy(hs_media_buff + buff_pos, data, len);
buff_pos += len;
}
// swallow the data peeked at before
pa_stream_drop(s);
}
return ;
}
/************************************************************************
************************************************************************/
int usbbtf_hs_stream_write (void *data, int length){
if(data == NULL){
return F_NG;
}
usbbt_conn_mode = USBBT_CONN_HEADSET;
if(u_task_tbl.media_sender_fd != -1){
write(u_task_tbl.media_sender_fd, data, length);
}
return F_OK;
}
/************************************************************************
************************************************************************/
int usbbtf_hs_stream_sender_write (void *data, int length){
struct timespec log_time;
if(data == NULL){
return F_NG;
}
if(ostream != NULL){
memset(&log_time, 0, sizeof(log_time));
clock_gettime(CLOCK_REALTIME, &log_time);
printf("HSET_W -> PA len: %d %ld %s", length, log_time.tv_nsec, ctime(&log_time.tv_sec));
if (pa_stream_write(ostream, (uint8_t*) data,
length, NULL, 0, PA_SEEK_RELATIVE) < 0) {
printf("pa_stream_write() failed \n");
return F_NG;
} else {
printf("pa_stream_write() OK len = %d\n", length);
}
}
return F_OK;
}
/************************************************************************
************************************************************************/
void usbbtf_hs_stream_state_cb_record (pa_stream *s, void *userdata){
printf("record status (%d)\n", pa_stream_get_state(s));
printf("usbbtf_hs_stream_state_cb_record Nop \n");
switch(pa_stream_get_state(s)){
case PA_STREAM_CREATING:
printf("Stream creating \n");
memset(hs_media_buff, 0, sizeof(hs_media_buff));
buff_pos = 0;
break;
case PA_STREAM_UNCONNECTED:
case PA_STREAM_READY:
case PA_STREAM_TERMINATED:
break;
case PA_STREAM_FAILED:
printf("Stream failed %s \n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
break;
}
}
/************************************************************************
************************************************************************/
void usbbtf_hs_stream_state_cb_playback (pa_stream *s, void *userdata){
printf("playback status (%d)\n", pa_stream_get_state(s));
printf("usbbtf_hs_stream_state_cb_playback Nop \n");
switch(pa_stream_get_state(s)){
case PA_STREAM_CREATING:
printf("Stream creating \n");
break;
case PA_STREAM_UNCONNECTED:
case PA_STREAM_READY:
case PA_STREAM_TERMINATED:
break;
case PA_STREAM_FAILED:
printf("Stream failed %s \n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
break;
}
}
/************************************************************************
************************************************************************/
void usbbtf_hs_context_state_cb (pa_context *c, void *userdata){
pa_context_state_t state;
pa_buffer_attr buffer_attr;
state = pa_context_get_state(c);
printf("State changed (%d)\n", state);
switch (state) {
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
break;
case PA_CONTEXT_READY:
if (!(istream = pa_stream_new(c, "IPKTRecord", &sample_spec, NULL))) {
printf("pa_stream_new() failed: %s", pa_strerror(pa_context_errno(c)));
return;
}
if (!(ostream = pa_stream_new(c, "IPKTPlayback", &sample_spec, NULL))) {
printf("pa_stream_new() failed: %s", pa_strerror(pa_context_errno(c)));
return;
}
pa_stream_set_state_callback(istream, usbbtf_hs_stream_state_cb_record, NULL);
pa_stream_set_read_callback(istream, usbbtf_hs_stream_read_cb, NULL);
memset(&buffer_attr, 0, sizeof(buffer_attr));
buffer_attr.maxlength = (uint32_t) -1;
buffer_attr.prebuf = (uint32_t) -1;
buffer_attr.minreq = (uint32_t) -1;
buffer_attr.tlength = (uint32_t) -1;
buffer_attr.fragsize = (uint32_t) -1;
if (pa_stream_connect_record(istream, NULL, &buffer_attr, 0) < 0) {
printf("pa_stream_connect_record() failed: %s", pa_strerror(pa_context_errno(c)));
return;
} else {
printf("Set record callback\n");
}
if (pa_stream_connect_playback(ostream, NULL, &buffer_attr, flags,
NULL,
NULL) < 0) {
printf("pa_stream_connect_playback() failed: %s", pa_strerror(pa_context_errno(c)));
return;
} else {
printf("Set playback callback\n");
}
break;
default:
printf("Unknown context status\n");
}
return;
}
/************************************************************************
************************************************************************/
int usbbtf_hs_start(){
pa_mainloop_api *pa_mlapi;
/* Create a threaded mainloop API and connection to the default server */
u_task_tbl.pa_ml = pa_threaded_mainloop_new();
pa_mlapi = pa_threaded_mainloop_get_api(u_task_tbl.pa_ml);
u_task_tbl.pa_ctx = pa_context_new(pa_mlapi, "ipkt_hs");
pa_threaded_mainloop_set_name(u_task_tbl.pa_ml, "ipkt_headset");
pa_context_connect(u_task_tbl.pa_ctx, NULL, 0, NULL);
/* This function defines a callback so the server will tell us its state. */
pa_context_set_state_callback(u_task_tbl.pa_ctx, usbbtf_hs_context_state_cb, NULL);
if (pa_threaded_mainloop_start(u_task_tbl.pa_ml) < 0) {
printf("pa_mainloop_start() failed.");
return F_NG;
}
return F_OK;
}
/************************************************************************
************************************************************************/
int usbbtf_hs_stop(){
if(u_task_tbl.pa_ctx == NULL || u_task_tbl.pa_ml == NULL){
return F_NG;
}
pa_context_disconnect(u_task_tbl.pa_ctx);
pa_threaded_mainloop_stop(u_task_tbl.pa_ml);
pa_threaded_mainloop_free(u_task_tbl.pa_ml);
u_task_tbl.pa_ctx = NULL;
u_task_tbl.pa_ml = NULL;
return F_OK;
}
_______________________________________________
pulseaudio-discuss mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss