Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49be8034 authored by Mingming Yin's avatar Mingming Yin
Browse files

hal: fix for surround sound recording

- Use proper period_size(512) and period_count(8)
  for 4ch pcm recording.
- Fix read logic in ssr_read to capture 4k data
  for each read
- Miscellaneous code clean up for variables, APIS,
  and debug dumps.

Change-Id: I01c0e99a717a3536bd7d19c2f46ed10be77661e4
Crs-Fixed: 589342
parent 694cb338
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -61,13 +61,6 @@ void audio_extn_hfp_set_parameters(adev, parms) (0)
void audio_extn_hfp_set_parameters(struct audio_device *adev,
                                           struct str_parms *parms);
#endif
#ifndef SSR_ENABLED
#define audio_extn_ssr_get_parameters(query, reply) (0)
#else
void audio_extn_ssr_get_parameters(struct str_parms *query,

                                          struct str_parms *reply);
#endif

#ifndef ANC_HEADSET_ENABLED
#define audio_extn_set_anc_parameters(adev, parms)       (0)
@@ -335,7 +328,6 @@ void audio_extn_get_parameters(const struct audio_device *adev,
                              struct str_parms *reply)
{
    audio_extn_get_afe_proxy_parameters(query, reply);
    audio_extn_ssr_get_parameters(query, reply);

    ALOGD("%s: returns %s", __func__, str_parms_to_str(reply));
}
+2 −2
Original line number Diff line number Diff line
@@ -70,14 +70,14 @@ bool audio_extn_usb_is_proxy_inuse();
#ifndef SSR_ENABLED
#define audio_extn_ssr_init(adev, in)                 (0)
#define audio_extn_ssr_deinit()                       (0)
#define audio_extn_ssr_update_enabled(adev)           (0)
#define audio_extn_ssr_update_enabled()               (0)
#define audio_extn_ssr_get_enabled()                  (0)
#define audio_extn_ssr_read(stream, buffer, bytes)    (0)
#else
int32_t audio_extn_ssr_init(struct audio_device *adev,
                            struct stream_in *in);
int32_t audio_extn_ssr_deinit();
int32_t audio_extn_ssr_update_enabled(struct audio_device *adev);
void audio_extn_ssr_update_enabled();
bool audio_extn_ssr_get_enabled();
int32_t audio_extn_ssr_read(struct audio_stream_in *stream,
                       void *buffer, size_t bytes);
+62 −177
Original line number Diff line number Diff line
@@ -36,12 +36,11 @@
#ifdef SSR_ENABLED
#define COEFF_ARRAY_SIZE            4
#define FILT_SIZE                   ((512+1)* 6)  /* # ((FFT bins)/2+1)*numOutputs */
#define SSR_FRAME_SIZE        512
#define SSR_INPUT_FRAME_SIZE  (SSR_FRAME_SIZE * 4)
#define SSR_OUTPUT_FRAME_SIZE (SSR_FRAME_SIZE * 6)
#define SSR_CHANNEL_COUNT     4
#define SSR_PERIOD_SIZE       256
#define SSR_CHANNEL_INPUT_NUM       4
#define SSR_CHANNEL_OUTPUT_NUM      6
#define SSR_PERIOD_COUNT            8
#define SSR_PERIOD_SIZE             512
#define SSR_INPUT_FRAME_SIZE        (SSR_PERIOD_SIZE * SSR_PERIOD_COUNT)

#define SURROUND_FILE_1R "/system/etc/surround_sound/filter1r.pcm"
#define SURROUND_FILE_2R "/system/etc/surround_sound/filter2r.pcm"
@@ -52,7 +51,7 @@
#define SURROUND_FILE_2I "/system/etc/surround_sound/filter2i.pcm"
#define SURROUND_FILE_3I "/system/etc/surround_sound/filter3i.pcm"
#define SURROUND_FILE_4I "/system/etc/surround_sound/filter4i.pcm"
#define AUDIO_PARAMETER_KEY_SSR "ssr"

#define LIB_SURROUND_PROC       "libsurround_proc.so"

typedef int  (*surround_filters_init_t)(void *, int, int, Word16 **,
@@ -67,11 +66,7 @@ struct ssr_module {
    int16_t             **real_coeffs;
    int16_t             **imag_coeffs;
    void                *surround_obj;

    int16_t             *surround_input_buffer;
    int16_t             *surround_output_buffer;
    int                 surround_input_bufferIdx;
    int                 surround_output_bufferIdx;
    int16_t             *surround_raw_buffer;
    bool                is_ssr_enabled;

    void *surround_filters_handle;
@@ -81,19 +76,13 @@ struct ssr_module {
    surround_filters_intl_process_t surround_filters_intl_process;
};

static int32_t ssr_init_surround_sound_lib(unsigned long buffersize);
static int32_t ssr_read_coeffs_from_file();

static struct ssr_module ssrmod = {
    .fp_4ch = NULL,
    .fp_6ch = NULL,
    .real_coeffs = NULL,
    .imag_coeffs = NULL,
    .surround_obj = NULL,
    .surround_output_buffer = NULL,
    .surround_input_buffer = NULL,
    .surround_output_bufferIdx = 0,
    .surround_input_bufferIdx= 0,
    .surround_raw_buffer = NULL,
    .is_ssr_enabled = 0,

    .surround_filters_handle = NULL,
@@ -230,32 +219,20 @@ static int32_t ssr_init_surround_sound_lib(unsigned long buffersize)
    int high_freq = 100;
    int i, ret = 0;

    ssrmod.surround_input_bufferIdx = 0;
    ssrmod.surround_output_bufferIdx = 0;

    if ( ssrmod.surround_obj ) {
        ALOGE("%s: ola filter library is already initialized", __func__);
        return 0;
    }

    /* Allocate memory for input buffer */
    ssrmod.surround_input_buffer = (Word16 *) calloc(2 * SSR_INPUT_FRAME_SIZE,
    ssrmod.surround_raw_buffer = (Word16 *) calloc(buffersize,
                                              sizeof(Word16));
    if ( !ssrmod.surround_input_buffer ) {
    if ( !ssrmod.surround_raw_buffer ) {
       ALOGE("%s: Memory allocation failure. Not able to allocate "
             "memory for surroundInputBuffer", __func__);
       goto init_fail;
    }

    /* Allocate memory for output buffer */
    ssrmod.surround_output_buffer = (Word16 *) calloc(2 * SSR_OUTPUT_FRAME_SIZE,
                                               sizeof(Word16));
    if ( !ssrmod.surround_output_buffer ) {
       ALOGE("%s: Memory allocation failure. Not able to "
             "allocate memory for surroundOutputBuffer", __func__);
       goto init_fail;
    }

    /* Allocate memory for real and imag coeffs array */
    ssrmod.real_coeffs = (Word16 **) calloc(COEFF_ARRAY_SIZE, sizeof(Word16 *));
    if ( !ssrmod.real_coeffs ) {
@@ -353,13 +330,9 @@ init_fail:
        free(ssrmod.surround_obj);
        ssrmod.surround_obj = NULL;
    }
    if (ssrmod.surround_output_buffer) {
        free(ssrmod.surround_output_buffer);
        ssrmod.surround_output_buffer = NULL;
    }
    if (ssrmod.surround_input_buffer) {
        free(ssrmod.surround_input_buffer);
        ssrmod.surround_input_buffer = NULL;
    if (ssrmod.surround_raw_buffer) {
        free(ssrmod.surround_raw_buffer);
        ssrmod.surround_raw_buffer = NULL;
    }
    if (ssrmod.real_coeffs){
        for (i =0; i<COEFF_ARRAY_SIZE; i++ ) {
@@ -385,7 +358,7 @@ init_fail:
    return -ENOMEM;
}

int32_t audio_extn_ssr_update_enabled(struct audio_device *adev)
void audio_extn_ssr_update_enabled()
{
    char ssr_enabled[PROPERTY_VALUE_MAX] = "false";

@@ -397,7 +370,6 @@ int32_t audio_extn_ssr_update_enabled(struct audio_device *adev)
        ALOGD("%s: surround sound recording is not supported", __func__);
        ssrmod.is_ssr_enabled = false;
    }
    return 0;
}

bool audio_extn_ssr_get_enabled()
@@ -414,12 +386,13 @@ int32_t audio_extn_ssr_init(struct audio_device *adev,
    uint32_t buffer_size;

    ALOGD("%s: ssr case ", __func__);
    in->config.channels = SSR_CHANNEL_COUNT;
    in->config.channels = SSR_CHANNEL_INPUT_NUM;
    in->config.period_size = SSR_PERIOD_SIZE;
    in->config.period_count = SSR_PERIOD_COUNT;

    buffer_size = (SSR_PERIOD_SIZE)*(SSR_PERIOD_COUNT);
    ALOGD("%s: buffer_size: %d", __func__, buffer_size);
    /* use 4k hardcoded buffer size for ssr*/
    buffer_size = SSR_INPUT_FRAME_SIZE;
    ALOGV("%s: buffer_size: %d", __func__, buffer_size);

    ret = ssr_init_surround_sound_lib(buffer_size);
    if (0 != ret) {
@@ -433,9 +406,9 @@ int32_t audio_extn_ssr_init(struct audio_device *adev,
        /* Remember to change file system permission of data(e.g. chmod 777 data/),
          otherwise, fopen may fail */
        if ( !ssrmod.fp_4ch)
    ssrmod.fp_4ch = fopen("/data/media/0/4ch_ssr.pcm", "wb");
            ssrmod.fp_4ch = fopen("/data/4ch.pcm", "wb");
        if ( !ssrmod.fp_6ch)
    ssrmod.fp_6ch = fopen("/data/media/0/6ch_ssr.pcm", "wb");
            ssrmod.fp_6ch = fopen("/data/6ch.pcm", "wb");
        if ((!ssrmod.fp_4ch) || (!ssrmod.fp_6ch))
            ALOGE("%s: mfp_4ch or mfp_6ch open failed: mfp_4ch:%p mfp_6ch:%p",
                  __func__, ssrmod.fp_4ch, ssrmod.fp_6ch);
@@ -449,7 +422,7 @@ int32_t audio_extn_ssr_deinit()
    int i;

    if (ssrmod.surround_obj) {
        ALOGD("%s: entry", __func__);
        ALOGV("%s: entry", __func__);
        ssrmod.surround_filters_release(ssrmod.surround_obj);
        if (ssrmod.surround_obj)
            free(ssrmod.surround_obj);
@@ -474,25 +447,21 @@ int32_t audio_extn_ssr_deinit()
            free(ssrmod.imag_coeffs);
            ssrmod.imag_coeffs = NULL;
        }
        if (ssrmod.surround_output_buffer){
            free(ssrmod.surround_output_buffer);
            ssrmod.surround_output_buffer = NULL;
        if (ssrmod.surround_raw_buffer) {
            free(ssrmod.surround_raw_buffer);
            ssrmod.surround_raw_buffer = NULL;
        }
        if (ssrmod.surround_input_buffer) {
            free(ssrmod.surround_input_buffer);
            ssrmod.surround_input_buffer = NULL;
        if (ssrmod.fp_4ch)
            fclose(ssrmod.fp_4ch);
        if (ssrmod.fp_6ch)
            fclose(ssrmod.fp_6ch);
    }

        if ( ssrmod.fp_4ch ) fclose(ssrmod.fp_4ch);
        if ( ssrmod.fp_6ch ) fclose(ssrmod.fp_6ch);
    }

    if(ssrmod.surround_filters_handle)
    {
    if(ssrmod.surround_filters_handle) {
        dlclose(ssrmod.surround_filters_handle);
        ssrmod.surround_filters_handle = NULL;
    }
    ALOGD("%s: exit", __func__);
    ALOGV("%s: exit", __func__);

    return 0;
}
@@ -500,120 +469,36 @@ int32_t audio_extn_ssr_deinit()
int32_t audio_extn_ssr_read(struct audio_stream_in *stream,
                       void *buffer, size_t bytes)
{
    int processed = 0;
    int processed_pending;
    void *buffer_start = buffer;
    unsigned period_bytes;
    unsigned period_samples;
    int read_pending, n;
    size_t read_bytes = 0;
    int samples = bytes >> 1;

    struct stream_in *in = (struct stream_in *)stream;
    struct audio_device *adev = in->dev;
    size_t peroid_bytes;
    int32_t ret;

    period_bytes = in->config.period_size;
    ALOGD("%s: period_size: %d", __func__, in->config.period_size);
    period_samples = period_bytes >> 1;
    /* Convert bytes for 6ch to 4ch*/
    peroid_bytes = (bytes / SSR_CHANNEL_OUTPUT_NUM) * SSR_CHANNEL_INPUT_NUM;

    if (!ssrmod.surround_obj)
    if (!ssrmod.surround_obj) {
        ALOGE("%s: surround_obj not initialized", __func__);
        return -ENOMEM;

    do {
            if (ssrmod.surround_output_bufferIdx > 0) {
                ALOGV("%s: copy processed output "
                     "to buffer, surround_output_bufferIdx = %d",
                     __func__, ssrmod.surround_output_bufferIdx);
                /* Copy processed output to buffer */
                processed_pending = ssrmod.surround_output_bufferIdx;
                if (processed_pending > (samples - processed)) {
                    processed_pending = (samples - processed);
                }
                memcpy(buffer, ssrmod.surround_output_buffer, processed_pending * sizeof(Word16));
                buffer = (char*)buffer + processed_pending * sizeof(Word16);
                processed += processed_pending;
                if (ssrmod.surround_output_bufferIdx > processed_pending) {
                    /* Shift leftover samples to beginning of the buffer */
                    memcpy(&ssrmod.surround_output_buffer[0],
                           &ssrmod.surround_output_buffer[processed_pending],
                           (ssrmod.surround_output_bufferIdx - processed_pending) * sizeof(Word16));
                }
                ssrmod.surround_output_bufferIdx -= processed_pending;
            }

            if (processed >= samples) {
                ALOGV("%s: done processing buffer, "
                     "processed = %d", __func__, processed);
                /* Done processing this buffer */
                break;
    }

            /* Fill input buffer until there is enough to process */
            read_pending = SSR_INPUT_FRAME_SIZE - ssrmod.surround_input_bufferIdx;
            read_bytes = ssrmod.surround_input_bufferIdx;
            while (in->pcm && read_pending > 0) {
                n = pcm_read(in->pcm, &ssrmod.surround_input_buffer[read_bytes],
                             period_bytes);
                ALOGV("%s: pcm_read() returned n = %d buffer:%p size:%d", __func__,
                    n, &ssrmod.surround_input_buffer[read_bytes], period_bytes);
                if (n && n != -EAGAIN) {
                    /* Recovery part of pcm_read. TODO:split recovery */
                    return (ssize_t)n;
                }
                else if (n < 0) {
                    /* Recovery is part of pcm_write. TODO split is later */
                    return (ssize_t)n;
                }
                else {
                    read_pending -= period_samples;
                    read_bytes += period_samples;
                }
            }


            if (ssrmod.fp_4ch) {
                fwrite( ssrmod.surround_input_buffer, 1,
                        SSR_INPUT_FRAME_SIZE * sizeof(Word16), ssrmod.fp_4ch);
    ret = pcm_read(in->pcm, ssrmod.surround_raw_buffer, peroid_bytes);
    if (ret < 0) {
        ALOGE("%s: %s ret:%d", __func__, pcm_get_error(in->pcm),ret);
        return ret;
    }

    /* apply ssr libs to conver 4ch to 6ch */
    ssrmod.surround_filters_intl_process(ssrmod.surround_obj,
                &ssrmod.surround_output_buffer[ssrmod.surround_output_bufferIdx],
                (Word16 *)ssrmod.surround_input_buffer);

            /* Shift leftover samples to beginning of input buffer */
            if (read_pending < 0) {
                memcpy(&ssrmod.surround_input_buffer[0],
                       &ssrmod.surround_input_buffer[SSR_INPUT_FRAME_SIZE],
                       (-read_pending) * sizeof(Word16));
            }
            ssrmod.surround_input_bufferIdx = -read_pending;
        buffer, ssrmod.surround_raw_buffer);

            if (ssrmod.fp_6ch) {
                fwrite( &ssrmod.surround_output_buffer[ssrmod.surround_output_bufferIdx],
                        1, SSR_OUTPUT_FRAME_SIZE * sizeof(Word16), ssrmod.fp_6ch);
            }

            ssrmod.surround_output_bufferIdx += SSR_OUTPUT_FRAME_SIZE;
            ALOGV("%s: do_while loop: processed=%d, samples=%d\n", __func__, processed, samples);
        } while (in->pcm && processed < samples);
        read_bytes = processed * sizeof(Word16);
        buffer = buffer_start;
    /*dump for raw pcm data*/
    if (ssrmod.fp_4ch)
        fwrite(ssrmod.surround_raw_buffer, 1, peroid_bytes, ssrmod.fp_4ch);
    if (ssrmod.fp_6ch)
        fwrite(buffer, 1, bytes, ssrmod.fp_6ch);

    return 0;
    return ret;
}

void audio_extn_ssr_get_parameters(struct str_parms *query,
                                   struct str_parms *reply)
{
    int ret, val;
    char value[32]={0};

    ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SSR, value, sizeof(value));

    if (ret >= 0) {
        memcpy(value, "true", 4);
        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SSR, value);
    }
}
#endif /* SSR_ENABLED */
+1 −1
Original line number Diff line number Diff line
@@ -561,7 +561,7 @@ void *platform_init(struct audio_device *adev)
    audio_extn_usb_set_proxy_sound_card(adev->snd_card);

    /* Read one time ssr property */
    audio_extn_ssr_update_enabled(adev);
    audio_extn_ssr_update_enabled();
    audio_extn_spkr_prot_init(adev);
    return my_data;
}