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

Commit e7231401 authored by Phil Burk's avatar Phil Burk Committed by Android (Google) Code Review
Browse files

Merge "aaudio: test 24 and 32 bit formats"

parents f56e1e4b b658630d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -421,7 +421,9 @@ public:
        printf("      -f{0|1|2} set format\n");
        printf("          0 = UNSPECIFIED\n");
        printf("          1 = PCM_I16\n");
        printf("          2 = FLOAT\n");
        printf("          2 = PCM_FLOAT\n");
        printf("          3 = PCM_I24_PACKED\n");
        printf("          4 = PCM_I32\n");
        printf("      -i{inputPreset} eg. 5 for AAUDIO_INPUT_PRESET_CAMCORDER\n");
        printf("      -m{0|1|2|3} set MMAP policy\n");
        printf("          0 = _UNSPECIFIED, use aaudio.mmap_policy system property, default\n");
+26 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
#define NANOS_PER_SECOND      (NANOS_PER_MILLISECOND * 1000)

// Use template functions to avoid warning of unused static functions.
template <class T = aaudio_sharing_mode_t>
const char *getSharingModeText(aaudio_sharing_mode_t mode) {
    const char *text = "unknown";
@@ -48,6 +49,7 @@ const char *getSharingModeText(aaudio_sharing_mode_t mode) {
    return text;
}

template <class T = aaudio_performance_mode_t>
const char *getPerformanceModeText(aaudio_performance_mode_t mode) {
    const char *text = "unknown";
    switch (mode) {
@@ -66,6 +68,7 @@ const char *getPerformanceModeText(aaudio_performance_mode_t mode) {
    return text;
}

template <class T = aaudio_direction_t>
const char *getDirectionText(aaudio_direction_t direction) {
    const char *text = "unknown";
    switch (direction) {
@@ -81,6 +84,29 @@ const char *getDirectionText(aaudio_direction_t direction) {
    return text;
}

template <class T = aaudio_direction_t>
constexpr int32_t getBytesPerSample(aaudio_format_t format) {
    switch (format) {
        case AAUDIO_FORMAT_PCM_I16:
            return 2;
        case AAUDIO_FORMAT_PCM_FLOAT:
            return 4;
        case AAUDIO_FORMAT_PCM_I24_PACKED:
            return 3;
        case AAUDIO_FORMAT_PCM_I32:
            return 4;
        default:
            return -1;
    }
}

// Return true if CPU is native Little Endian
inline bool isNativeLittleEndian() {
    // If the first byte of the data word in memory is 1 then Little Endian.
    constexpr union { unsigned u; unsigned char c[sizeof(unsigned)]; } one = {1};
    return one.c[0] != 0;
}

template <class T = int64_t>
void convertNanosecondsToTimespec(int64_t nanoseconds, struct timespec *time) {
    time->tv_sec = nanoseconds / NANOS_PER_SECOND;
+24 −8
Original line number Diff line number Diff line
@@ -359,22 +359,38 @@ aaudio_data_callback_result_t SimplePlayerDataCallbackProc(

    int32_t samplesPerFrame = AAudioStream_getChannelCount(stream);


    int numActiveOscilators = (samplesPerFrame > MAX_CHANNELS) ? MAX_CHANNELS : samplesPerFrame;
    int numActiveOscillators = std::min(samplesPerFrame, MAX_CHANNELS);
    switch (AAudioStream_getFormat(stream)) {
        case AAUDIO_FORMAT_PCM_I16: {
            int16_t *audioBuffer = (int16_t *) audioData;
            for (int i = 0; i < numActiveOscilators; ++i) {
                sineData->sineOscillators[i].render(&audioBuffer[i], samplesPerFrame,
                                                    numFrames);
            for (int i = 0; i < numActiveOscillators; ++i) {
                sineData->sineOscillators[i].render(&audioBuffer[i],
                                                    samplesPerFrame, numFrames);
            }
        }
            break;
        case AAUDIO_FORMAT_PCM_FLOAT: {
            float *audioBuffer = (float *) audioData;
            for (int i = 0; i < numActiveOscilators; ++i) {
                sineData->sineOscillators[i].render(&audioBuffer[i], samplesPerFrame,
                                                    numFrames);
            for (int i = 0; i < numActiveOscillators; ++i) {
                sineData->sineOscillators[i].render(&audioBuffer[i],
                                                    samplesPerFrame, numFrames);
            }
        }
            break;
        case AAUDIO_FORMAT_PCM_I24_PACKED: {
            uint8_t *audioBuffer = (uint8_t *) audioData;
            for (int i = 0; i < numActiveOscillators; ++i) {
                static const int bytesPerSample = getBytesPerSample(AAUDIO_FORMAT_PCM_I24_PACKED);
                sineData->sineOscillators[i].render24(&audioBuffer[i * bytesPerSample],
                                                      samplesPerFrame, numFrames);
            }
        }
            break;
        case AAUDIO_FORMAT_PCM_I32: {
            int32_t *audioBuffer = (int32_t *) audioData;
            for (int i = 0; i < numActiveOscillators; ++i) {
                sineData->sineOscillators[i].render(&audioBuffer[i],
                                                    samplesPerFrame, numFrames);
            }
        }
            break;
+38 −5
Original line number Diff line number Diff line
@@ -41,20 +41,54 @@ public:
        }
    }

    float next() {
        float value = sinf(mPhase) * mAmplitude;
        advancePhase();
        return value;
    }

    void render(int16_t *buffer, int32_t channelStride, int32_t numFrames) {
        int sampleIndex = 0;
        for (int i = 0; i < numFrames; i++) {
            buffer[sampleIndex] = (int16_t) (INT16_MAX * sin(mPhase) * mAmplitude);
            buffer[sampleIndex] = (int16_t) (INT16_MAX * next());
            sampleIndex += channelStride;
            advancePhase();
        }
    }

    void render(float *buffer, int32_t channelStride, int32_t numFrames) {
        int sampleIndex = 0;
        for (int i = 0; i < numFrames; i++) {
            buffer[sampleIndex] = sin(mPhase) * mAmplitude;
            buffer[sampleIndex] = next();
            sampleIndex += channelStride;
            advancePhase();
        }
    }

    void render(int32_t *buffer, int32_t channelStride, int32_t numFrames) {
        int sampleIndex = 0;
        for (int i = 0; i < numFrames; i++) {
            buffer[sampleIndex] = (int32_t) (INT32_MAX * next());
            sampleIndex += channelStride;
        }
    }

    void render24(uint8_t *buffer, int32_t channelStride, int32_t numFrames) {
        int sampleIndex = 0;
        constexpr int32_t INT24_MAX = (1 << 23) - 1;
        constexpr int bytesPerSample = getBytesPerSample(AAUDIO_FORMAT_PCM_I24_PACKED);
        const bool isLittleEndian = isNativeLittleEndian();
        for (int i = 0; i < numFrames; i++) {
            int32_t sample = (int32_t) (INT24_MAX * next());
            uint32_t usample = (uint32_t) sample;
            if (isLittleEndian) {
                buffer[sampleIndex] = usample; // little end first
                buffer[sampleIndex + 1] = usample >> 8;
                buffer[sampleIndex + 2] = usample >> 16;
            } else {
                buffer[sampleIndex] = usample >> 16; // big end first
                buffer[sampleIndex + 1] = usample >> 8;
                buffer[sampleIndex + 2] = usample;
            }
            sampleIndex += channelStride * bytesPerSample;
        }
    }

@@ -100,4 +134,3 @@ private:
};

#endif /* SINE_GENERATOR_H */
+65 −24
Original line number Diff line number Diff line
@@ -47,9 +47,11 @@ int main(int argc, const char **argv)
    int32_t  framesToPlay = 0;
    int32_t  framesLeft = 0;
    int32_t  xRunCount = 0;
    int      numActiveOscilators = 0;
    int      numActiveOscillators = 0;
    float   *floatData = nullptr;
    int16_t *shortData = nullptr;
    int32_t *int32Data = nullptr;
    uint8_t *byteData = nullptr;

    int      testFd = -1;

@@ -57,7 +59,7 @@ int main(int argc, const char **argv)
    // in a buffer if we hang or crash.
    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);

    printf("%s - Play a sine wave using AAudio V0.1.3\n", argv[0]);
    printf("%s - Play a sine wave using AAudio V0.1.4\n", argv[0]);

    if (argParser.parseArgs(argc, argv)) {
        return EXIT_FAILURE;
@@ -91,11 +93,21 @@ int main(int argc, const char **argv)
    printf("Buffer: framesPerWrite = %d\n",framesPerWrite);

    // Allocate a buffer for the audio data.
    if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
    switch (actualDataFormat) {
        case AAUDIO_FORMAT_PCM_FLOAT:
            floatData = new float[framesPerWrite * actualChannelCount];
    } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
            break;
        case AAUDIO_FORMAT_PCM_I16:
            shortData = new int16_t[framesPerWrite * actualChannelCount];
    } else {
            break;
        case AAUDIO_FORMAT_PCM_I24_PACKED:
            byteData = new uint8_t[framesPerWrite * actualChannelCount
                                   * getBytesPerSample(AAUDIO_FORMAT_PCM_I24_PACKED)];
            break;
        case AAUDIO_FORMAT_PCM_I32:
            int32Data = new int32_t[framesPerWrite * actualChannelCount];
            break;
        default:
            printf("ERROR Unsupported data format!\n");
            goto finish;
    }
@@ -117,29 +129,56 @@ int main(int argc, const char **argv)
    // Play for a while.
    framesToPlay = actualSampleRate * argParser.getDurationSeconds();
    framesLeft = framesToPlay;
    numActiveOscilators = (actualChannelCount > MAX_CHANNELS) ? MAX_CHANNELS : actualChannelCount;
    numActiveOscillators = (actualChannelCount > MAX_CHANNELS) ? MAX_CHANNELS : actualChannelCount;
    while (framesLeft > 0) {
        // Render as FLOAT or PCM
        if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
            for (int i = 0; i < numActiveOscilators; ++i) {
        switch (actualDataFormat) {
            case AAUDIO_FORMAT_PCM_FLOAT:
                for (int i = 0; i < numActiveOscillators; ++i) {
                    myData.sineOscillators[i].render(&floatData[i], actualChannelCount,
                                                     framesPerWrite);
                }
        } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
            for (int i = 0; i < numActiveOscilators; ++i) {
                break;
            case AAUDIO_FORMAT_PCM_I16:
                for (int i = 0; i < numActiveOscillators; ++i) {
                    myData.sineOscillators[i].render(&shortData[i], actualChannelCount,
                                                     framesPerWrite);
                }
                break;
            case AAUDIO_FORMAT_PCM_I32:
                for (int i = 0; i < numActiveOscillators; ++i) {
                    myData.sineOscillators[i].render(&int32Data[i], actualChannelCount,
                                                     framesPerWrite);
                }
                break;
            case AAUDIO_FORMAT_PCM_I24_PACKED:
                for (int i = 0; i < numActiveOscillators; ++i) {
                    static const int
                        bytesPerSample = getBytesPerSample(AAUDIO_FORMAT_PCM_I24_PACKED);
                    myData.sineOscillators[i].render24(&byteData[i * bytesPerSample],
                                                       actualChannelCount,
                                                       framesPerWrite);
                }
                break;
        }

        // Write audio data to the stream.
        int64_t timeoutNanos = 1000 * NANOS_PER_MILLISECOND;
        int32_t minFrames = (framesToPlay < framesPerWrite) ? framesToPlay : framesPerWrite;
        int32_t actual = 0;
        if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
        switch (actualDataFormat) {
            case AAUDIO_FORMAT_PCM_FLOAT:
                actual = AAudioStream_write(aaudioStream, floatData, minFrames, timeoutNanos);
        } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
                break;
            case AAUDIO_FORMAT_PCM_I16:
                actual = AAudioStream_write(aaudioStream, shortData, minFrames, timeoutNanos);
                break;
            case AAUDIO_FORMAT_PCM_I32:
                actual = AAudioStream_write(aaudioStream, int32Data, minFrames, timeoutNanos);
                break;
            case AAUDIO_FORMAT_PCM_I24_PACKED:
                actual = AAudioStream_write(aaudioStream, byteData, minFrames, timeoutNanos);
                break;
        }
        if (actual < 0) {
            fprintf(stderr, "ERROR - AAudioStream_write() returned %d\n", actual);
@@ -196,6 +235,8 @@ finish:

    delete[] floatData;
    delete[] shortData;
    delete[] int32Data;
    delete[] byteData;
    printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
    return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS;
}
Loading