summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOscar Azucena <oscarazu@google.com>2020-06-08 11:45:37 -0700
committerOscar Azucena <oscarazu@google.com>2020-06-12 13:18:01 -0700
commit535033cb4a324f9695ae6c7226b0de2607387dcd (patch)
tree1e371996076f7d77653f2583f8f7bebf314b02f3
parent68de103e7f29989dac916ade3d543237defb5184 (diff)
downloaddevice_generic_car-535033cb4a324f9695ae6c7226b0de2607387dcd.tar.gz
device_generic_car-535033cb4a324f9695ae6c7226b0de2607387dcd.tar.bz2
device_generic_car-535033cb4a324f9695ae6c7226b0de2607387dcd.zip
Added simulated input devices to HW sound emulator.
Added simulated audio input devices to car audio configuration. This devices can be used for any audio zone in particular but are mostly set to target zone 0 and zone 1. Also added osillator struct to keep track of phase and current phase increment (e.g ~frequency) to keep track of current phase changes in simulated input device. Test: m -j, run emulator Bug: 158122733 Change-Id: Iecdcd695975b71ce4d49c0770bd9ea02f9703cd3
-rw-r--r--emulator/audio/audio_policy_configuration.xml32
-rw-r--r--emulator/audio/driver/audio_hw.c95
-rw-r--r--emulator/audio/driver/audio_hw.h10
3 files changed, 115 insertions, 22 deletions
diff --git a/emulator/audio/audio_policy_configuration.xml b/emulator/audio/audio_policy_configuration.xml
index 6574cc6..ed0f4a6 100644
--- a/emulator/audio/audio_policy_configuration.xml
+++ b/emulator/audio/audio_policy_configuration.xml
@@ -67,6 +67,8 @@
<item>Built-In Back Mic</item>
<item>Echo-Reference Mic</item>
<item>FM Tuner</item>
+ <item>Tone Generator 0</item>
+ <item>Tone Generator 1</item>
</attachedDevices>
<defaultOutputDevice>bus0_media_out</defaultOutputDevice>
<mixPorts>
@@ -140,6 +142,16 @@
samplingRates="48000"
channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>
+ <mixPort name="mixport_input_bus_tone_zone_0" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_input_bus_tone_zone_1" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
@@ -256,6 +268,24 @@
minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
+ <devicePort tagName="Tone Generator 0" type="AUDIO_DEVICE_IN_BUS" role="source"
+ address="input_bus_tone_zone_0">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Tone Generator 1" type="AUDIO_DEVICE_IN_BUS" role="source"
+ address="input_bus_tone_zone_1">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ </gains>
+ </devicePort>
</devicePorts>
<!-- route declaration, i.e. list all available sources for a given sink -->
<routes>
@@ -271,6 +301,8 @@
<route type="mix" sink="bus200_audio_zone_2" sources="mixport_bus200_audio_zone_2"/>
<route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,Echo-Reference Mic"/>
<route type="mix" sink="mixport_tuner0" sources="FM Tuner"/>
+ <route type="mix" sink="mixport_input_bus_tone_zone_0" sources="Tone Generator 0"/>
+ <route type="mix" sink="mixport_input_bus_tone_zone_1" sources="Tone Generator 1"/>
</routes>
</module>
diff --git a/emulator/audio/driver/audio_hw.c b/emulator/audio/driver/audio_hw.c
index 0a465b6..bc27e90 100644
--- a/emulator/audio/driver/audio_hw.c
+++ b/emulator/audio/driver/audio_hw.c
@@ -51,19 +51,26 @@
#define IN_PERIOD_MS 15
#define IN_PERIOD_COUNT 4
+#define PI 3.14159265
+#define TWO_PI (2*PI)
+
+// 150 Hz
+#define DEFAULT_FREQUENCY 150
+// Increase in changes to tone frequency
+#define TONE_FREQUENCY_INCREASE 20
+// Max tone frequency to auto assign, don't want to generate too high of a pitch
+#define MAX_TONE_FREQUENCY 500
+
#define _bool_str(x) ((x)?"true":"false")
static const char * const PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO = "ro.aae.simulateMultiZoneAudio";
static const char * const AAE_PARAMETER_KEY_FOR_SELECTED_ZONE = "com.android.car.emulator.selected_zone";
-// Lapse time between checking audio id changes
-#define DEFAULT_PLAYZONE_ID_ELAPSE_TIME_MS 300.0f
-#define MILLISECONDS_TO_MICROSECONDS 1000.0f
-#define SECONDS_TO_MILLISECONDS 1000.0f
#define PRIMARY_ZONE_ID 0
#define INVALID_ZONE_ID -1
// Note the primary zone goes to left speaker so route other zone to right speaker
#define DEFAULT_ZONE_TO_LEFT_SPEAKER (PRIMARY_ZONE_ID + 1)
+static const char * const TONE_ADDRESS_KEYWORD = "_tone_";
static const char * const AUDIO_ZONE_KEYWORD = "_audio_zone_";
#define SIZE_OF_PARSE_BUFFER 32
@@ -105,11 +112,6 @@ static struct pcm_config pcm_config_in = {
.stop_threshold = INT_MAX,
};
-float time_difference_msec(struct timeval t0, struct timeval t1) {
- return (t1.tv_sec - t0.tv_sec) * SECONDS_TO_MILLISECONDS +
- (t1.tv_usec - t0.tv_usec) / MILLISECONDS_TO_MICROSECONDS;
-}
-
static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
static unsigned int audio_device_ref_count = 0;
@@ -796,14 +798,17 @@ static int in_standby(struct audio_stream *stream) {
return 0;
}
-#define STEP (3.14159265 / 180)
-// Generates pure tone for FM_TUNER
-static int pseudo_pcm_read(void *data, unsigned int count) {
- unsigned int length = count / sizeof(short);
- short *sdata = (short *)data;
+// Generates pure tone for FM_TUNER and bus_device
+static int pseudo_pcm_read(void *data, unsigned int count, struct oscillator *oscillator) {
+ unsigned int length = count / sizeof(int16_t);
+ int16_t *sdata = (int16_t *)data;
for (int index = 0; index < length; index++) {
- sdata[index] = (short)(sin(index * STEP) * 4096);
+ sdata[index] = (int16_t)(sin(oscillator->phase) * 4096);
+ oscillator->phase += oscillator->phase_increment;
+ oscillator->phase = oscillator->phase > TWO_PI ?
+ oscillator->phase - TWO_PI : oscillator->phase;
}
+
return count;
}
@@ -885,6 +890,15 @@ static void *in_read_worker(void *args) {
return NULL;
}
+static bool address_has_tone_keyword(char * address) {
+ return strstr(address, TONE_ADDRESS_KEYWORD) != NULL;
+}
+
+static bool is_tone_generator_device(struct generic_stream_in *in) {
+ return in->device == AUDIO_DEVICE_IN_FM_TUNER || ((in->device == AUDIO_DEVICE_IN_BUS) &&
+ address_has_tone_keyword(in->bus_address));
+}
+
static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t bytes) {
struct generic_stream_in *in = (struct generic_stream_in *)stream;
struct generic_audio_device *adev = in->dev;
@@ -899,8 +913,9 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte
if (in->worker_standby) {
in->worker_standby = false;
}
- // FM_TUNER fills the buffer via pseudo_pcm_read directly
- if (in->device != AUDIO_DEVICE_IN_FM_TUNER) {
+
+ // Tone generators fill the buffer via pseudo_pcm_read directly
+ if (!is_tone_generator_device(in)) {
pthread_cond_signal(&in->worker_wake);
}
@@ -937,8 +952,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte
}
in->standby_frames_read += frames;
- if (in->device == AUDIO_DEVICE_IN_FM_TUNER) {
- int read_bytes = pseudo_pcm_read(buffer, bytes);
+ if (is_tone_generator_device(in)) {
+ int read_bytes = pseudo_pcm_read(buffer, bytes, &in->oscillator);
read_frames = read_bytes / audio_stream_in_frame_size(stream);
} else if (popcount(in->req_config.channel_mask) == 1 &&
in->pcm_config.channels == 2) {
@@ -1140,7 +1155,7 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
return results;
}
-static char *adev_get_parameters(const struct audio_hw_device *dev, const char *keys) {
+static char *adev_get_parameters(const struct audio_hw_device * dev, const char *keys) {
return NULL;
}
@@ -1230,6 +1245,25 @@ static void adev_close_input_stream(struct audio_hw_device *dev,
free(stream);
}
+static void increase_next_tone_frequency(struct generic_audio_device *adev) {
+ adev->next_tone_frequency_to_assign += TONE_FREQUENCY_INCREASE;
+ if (adev->next_tone_frequency_to_assign > MAX_TONE_FREQUENCY) {
+ adev->next_tone_frequency_to_assign = DEFAULT_FREQUENCY;
+ }
+}
+
+static int create_or_fetch_tone_frequency(struct generic_audio_device *adev,
+ char *address, int update_frequency) {
+ int *frequency = hashmapGet(adev->in_bus_tone_frequency_map, address);
+ if (frequency == NULL) {
+ frequency = calloc(1, sizeof(int));
+ *frequency = update_frequency;
+ hashmapPut(adev->in_bus_tone_frequency_map, strdup(address), frequency);
+ ALOGD("%s assigned frequency %d to %s", __func__, *frequency, address);
+ }
+ return *frequency;
+}
+
static int adev_open_input_stream(struct audio_hw_device *dev,
audio_io_handle_t handle, audio_devices_t devices, struct audio_config *config,
struct audio_stream_in **stream_in, audio_input_flags_t flags __unused, const char *address,
@@ -1297,8 +1331,17 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
}
if (address) {
- in->bus_address = calloc(strlen(address) + 1, sizeof(char));
- strncpy(in->bus_address, address, strlen(address));
+ in->bus_address = strdup(address);
+ if (is_tone_generator_device(in)) {
+ int update_frequency = adev->next_tone_frequency_to_assign;
+ int frequency = create_or_fetch_tone_frequency(adev, address, update_frequency);
+ if (update_frequency == frequency) {
+ increase_next_tone_frequency(adev);
+ }
+ in->oscillator.phase = 0.0f;
+ in->oscillator.phase_increment = (TWO_PI*(frequency))
+ / ((float) in_get_sample_rate(&in->stream.common));
+ }
}
*stream_in = &in->stream;
@@ -1395,6 +1438,9 @@ static int adev_close(hw_device_t *dev) {
if (adev->out_bus_stream_map) {
hashmapFree(adev->out_bus_stream_map);
}
+ if (adev->in_bus_tone_frequency_map) {
+ hashmapFree(adev->in_bus_tone_frequency_map);
+ }
free(adev);
}
@@ -1504,6 +1550,11 @@ static int adev_open(const hw_module_t *module,
// Initialize the bus address to output stream map
adev->out_bus_stream_map = hashmapCreate(5, str_hash_fn, str_eq);
+ // Initialize the bus address to input stream map
+ adev->in_bus_tone_frequency_map = hashmapCreate(5, str_hash_fn, str_eq);
+
+ adev->next_tone_frequency_to_assign = DEFAULT_FREQUENCY;
+
adev->last_zone_selected_to_play = DEFAULT_ZONE_TO_LEFT_SPEAKER;
audio_device_ref_count++;
diff --git a/emulator/audio/driver/audio_hw.h b/emulator/audio/driver/audio_hw.h
index 6b6148a..d195a53 100644
--- a/emulator/audio/driver/audio_hw.h
+++ b/emulator/audio/driver/audio_hw.h
@@ -33,6 +33,8 @@ struct generic_audio_device {
bool mic_mute; // Protected by this->lock
struct mixer *mixer; // Protected by this->lock
Hashmap *out_bus_stream_map; // Extended field. Constant after init
+ Hashmap *in_bus_tone_frequency_map; // Extended field. Constant after init
+ int next_tone_frequency_to_assign; // Protected by this->lock
// Play on Speaker zone selection
int last_zone_selected_to_play; // Protected by this->lock
};
@@ -72,6 +74,11 @@ struct generic_stream_out {
bool worker_exit; // Protected by this->lock
};
+struct oscillator {
+ float phase;
+ float phase_increment;
+};
+
struct generic_stream_in {
struct audio_stream_in stream; // Constant after init
pthread_mutex_t lock;
@@ -96,6 +103,9 @@ struct generic_stream_in {
pthread_cond_t worker_wake; // Protected by this->lock
bool worker_standby; // Protected by this->lock
bool worker_exit; // Protected by this->lock
+
+ // Tone Oscillator
+ struct oscillator oscillator; // Protected by this->lock
};
#endif // AUDIO_HW_H