Skip to content

Commit d04fa5d

Browse files
committed
audio: Impl channel adjustment for input sound to allow Mic capture
Fix the issue where applications can not capture a sound through Tinyhal with requested channel count less than 8 (the min/max interval for allowed channel count values is set to [8..8] in 'pcm3168a' driver, so pcm_open() function returns error in case count != 8). Implement a patch that provides a channel adjustment for input sound by converting the 8-channel flow to requested Mono or Stereo flow. Signed-off-by: Oleksandr Bobro <oleksandr.bobro@globallogic.com>
1 parent 5ae55d0 commit d04fa5d

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

audio/Android.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ ifeq ($(strip $(TINYHAL_COMPRESS_PLAYBACK)),true)
7676
LOCAL_CFLAGS += -DTINYHAL_COMPRESS_PLAYBACK
7777
endif
7878

79+
ifeq ($(TARGET_DEVICE),kingfisher)
80+
LOCAL_CFLAGS += -DPLATFORM_RCAR3
81+
endif
82+
7983
include $(BUILD_SHARED_LIBRARY)
8084

8185
endif

audio/audio_hw.c

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#endif
4949

5050
#include <audio_utils/resampler.h>
51+
#include <audio_utils/channels.h>
5152

5253
#include <tinyhal/audio_config.h>
5354

@@ -57,6 +58,23 @@
5758
#include <vendor/cirrus/scchal/scc_audio.h>
5859
#endif
5960

61+
#ifdef PLATFORM_RCAR3
62+
/* R-Car3 driver supports only 8-channel streams and 48000 sample rate */
63+
/* These values are defined in _frames_ (not bytes) to match the ALSA API */
64+
#define OUT_PERIOD_SIZE_DEFAULT 256
65+
#define OUT_PERIOD_COUNT_DEFAULT 4
66+
#define OUT_CHANNEL_MASK_DEFAULT AUDIO_CHANNEL_OUT_7POINT1
67+
#define OUT_CHANNEL_COUNT_DEFAULT 8
68+
#define OUT_RATE_DEFAULT 48000
69+
70+
#define IN_PERIOD_SIZE_DEFAULT 256
71+
#define IN_PERIOD_COUNT_DEFAULT 4
72+
#define IN_CHANNEL_MASK_DEFAULT AUDIO_CHANNEL_IN_STEREO
73+
#define IN_CHANNEL_COUNT_DEFAULT 8
74+
#define IN_RATE_DEFAULT 48000
75+
76+
#else
77+
6078
/* These values are defined in _frames_ (not bytes) to match the ALSA API */
6179
#define OUT_PERIOD_SIZE_DEFAULT 256
6280
#define OUT_PERIOD_COUNT_DEFAULT 4
@@ -70,6 +88,8 @@
7088
#define IN_CHANNEL_COUNT_DEFAULT 1
7189
#define IN_RATE_DEFAULT 44100
7290

91+
#endif
92+
7393
#define IN_PCM_BUFFER_SIZE_DEFAULT \
7494
(IN_PERIOD_SIZE_DEFAULT * IN_CHANNEL_COUNT_DEFAULT * sizeof(uint16_t))
7595

@@ -234,6 +254,9 @@ struct stream_in_pcm {
234254
uint32_t period_size; /* ... of PCM input */
235255

236256
struct in_resampler resampler;
257+
258+
void *pre_read_buf; /* Buffer to store read data before channel adjustment*/
259+
size_t pre_read_buf_size;
237260
};
238261

239262
static uint32_t out_get_sample_rate(const struct audio_stream *stream);
@@ -1660,6 +1683,11 @@ static unsigned int in_pcm_cfg_rate(struct stream_in_pcm *in)
16601683

16611684
static unsigned int in_pcm_cfg_channel_count(struct stream_in_pcm *in)
16621685
{
1686+
#ifdef PLATFORM_RCAR3
1687+
/* On R-Car3 driver supports only 8 channels reading */
1688+
return IN_CHANNEL_COUNT_DEFAULT;
1689+
#endif
1690+
16631691
if (in->common.channel_count != 0) {
16641692
return in->common.channel_count;
16651693
} else {
@@ -1741,6 +1769,22 @@ static int do_open_pcm_input(struct stream_in_pcm *in)
17411769

17421770
ALOGV("input buffer size=0x%zx", in->common.buffer_size);
17431771

1772+
if (in->common.channel_count != in->hw_channel_count) {
1773+
ALOGV("Setup buffer to read %d channel stream with adjustment (HW only supports %d channel reading)",
1774+
in->common.channel_count, in->hw_channel_count);
1775+
in->pre_read_buf_size = in->common.buffer_size * in->hw_channel_count / in->common.channel_count;
1776+
ALOGV("in->pre_read_buf_size=0x%zx", in->pre_read_buf_size);
1777+
in->pre_read_buf = calloc(1, in->pre_read_buf_size);
1778+
if (!in->pre_read_buf) {
1779+
ret = -ENOMEM;
1780+
goto fail;
1781+
}
1782+
}
1783+
else {
1784+
in->pre_read_buf = NULL;
1785+
in->pre_read_buf_size = 0;
1786+
}
1787+
17441788
/*
17451789
* If the stream rate differs from the PCM rate, we need to
17461790
* create a resampler.
@@ -1758,6 +1802,8 @@ static int do_open_pcm_input(struct stream_in_pcm *in)
17581802
fail:
17591803
pcm_close(in->pcm);
17601804
in->pcm = NULL;
1805+
if (in->pre_read_buf)
1806+
free(in->pre_read_buf);
17611807
exit:
17621808
ALOGV("-do_open_pcm_input error:%d", ret);
17631809
return ret;
@@ -1864,6 +1910,8 @@ static ssize_t do_in_pcm_read(struct audio_stream_in *stream, void *buffer,
18641910
int ret = 0;
18651911
struct stream_in_pcm *in = (struct stream_in_pcm *)stream;
18661912
size_t frames_rq = bytes / in->common.frame_size;
1913+
void *read_buf;
1914+
size_t read_buf_size;
18671915

18681916
ALOGV("+do_in_pcm_read %zu", bytes);
18691917

@@ -1874,10 +1922,39 @@ static ssize_t do_in_pcm_read(struct audio_stream_in *stream, void *buffer,
18741922
goto exit;
18751923
}
18761924

1925+
if (in->pre_read_buf) {
1926+
read_buf = in->pre_read_buf;
1927+
read_buf_size = in->pre_read_buf_size;
1928+
} else {
1929+
read_buf = buffer;
1930+
read_buf_size = bytes;
1931+
}
1932+
18771933
if (in->resampler.resampler != NULL) {
1878-
ret = read_resampled_frames(in, buffer, frames_rq);
1934+
ret = read_resampled_frames(in, read_buf, frames_rq);
18791935
} else {
1880-
ret = pcm_read(in->pcm, buffer, bytes);
1936+
ret = pcm_read(in->pcm, read_buf, read_buf_size);
1937+
}
1938+
1939+
if (ret < 0)
1940+
goto exit;
1941+
1942+
if (in->common.channel_count != in->hw_channel_count) {
1943+
1944+
ALOGV("do_in_pcm_read(): Adjust %d channel read stream to %d channel stream",
1945+
in->hw_channel_count, in->common.channel_count);
1946+
1947+
bytes = adjust_channels(read_buf, /* Input buffer */
1948+
in->hw_channel_count, /* Input channel count */
1949+
buffer, /* Output buffer */
1950+
in->common.channel_count, /* Output channel count */
1951+
in->common.frame_size / in->common.channel_count, /* Sample size */
1952+
read_buf_size /* Size of input buffer in bytes */
1953+
);
1954+
if (!bytes) {
1955+
ALOGE("do_in_pcm_read(): Failed to adjust channels");
1956+
ret = -1;
1957+
}
18811958
}
18821959

18831960
/* Assume any non-negative return is a successful read */
@@ -2015,6 +2092,14 @@ static void do_close_in_pcm(struct audio_stream *stream)
20152092
{
20162093
struct stream_in_pcm *in = (struct stream_in_pcm *)stream;
20172094

2095+
ALOGV("do_close_in_pcm(%p)", in);
2096+
if (in && in->pre_read_buf)
2097+
{
2098+
free(in->pre_read_buf);
2099+
in->pre_read_buf = NULL;
2100+
in->pre_read_buf_size = 0;
2101+
}
2102+
20182103
do_close_in_common(stream);
20192104
}
20202105

0 commit comments

Comments
 (0)