1ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner/* Copyright (C) 2010 The Android Open Source Project
2ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner**
3ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner** This software is licensed under the terms of the GNU General Public
4ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner** License version 2, as published by the Free Software Foundation, and
5ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner** may be copied, distributed, and modified under those terms.
6ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner**
7ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner** This program is distributed in the hope that it will be useful,
8ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner** but WITHOUT ANY WARRANTY; without even the implied warranty of
9ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner** GNU General Public License for more details.
11ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner*/
12ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner#include "audio/audio.h"
13ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner#include "android/utils/debug.h"
14ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
15ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner/* This source file contains a small test audio virtual device that
16ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner * can be used to check that the emulator properly plays sound on
17ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner * the host system without having to boot a full system.
18ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner */
19ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
20ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner#define SAMPLE_SIZE  16384
21ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
22ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turnertypedef struct {
23ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    QEMUSoundCard  card;
24ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    SWVoiceOut    *voice;
25ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    int            pos;
26ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    short          sample[SAMPLE_SIZE];
27ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner} TestAudio;
28ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
29ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turnerstatic void
30ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' TurnertestAudio_audio_callback(void* opaque, int free)
31ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner{
32ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    TestAudio* ta = opaque;
33ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
34ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    //printf("%s: pos=%d free=%d\n", __FUNCTION__, ta->pos, free);
35ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
36ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    while (free > 0) {
37ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        int  avail = SAMPLE_SIZE - ta->pos;
38ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        if (avail > free)
39ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner            avail = free;
40ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
41ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        AUD_write(ta->voice, ta->sample + ta->pos, avail);
42ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        ta->pos += avail;
43ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        if (ta->pos >= SAMPLE_SIZE)
44ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner            ta->pos = 0;
45ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
46ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        free -= avail;
47ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    }
48ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner}
49ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
50ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turnerstatic int
51ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' TurnertestAudio_init( TestAudio* ta )
52ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner{
53ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    struct audsettings as;
54ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
55ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    AUD_register_card("test_audio", &ta->card);
56ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
57ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    as.freq       = 16000;
58ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    as.nchannels  = 1;
59ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    as.fmt        = AUD_FMT_S16;
60ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    as.endianness = AUDIO_HOST_ENDIANNESS;
61ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
62ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    ta->voice = AUD_open_out(
63ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        &ta->card,
64ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        ta->voice,
65ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        "test_audio",
66ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        ta,
67ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        testAudio_audio_callback,
68ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        &as);
69ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
70ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    if (!ta->voice) {
71ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        dprint("Cannot open test audio!");
72ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        return -1;
73ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    }
74ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    ta->pos = 0;
75ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
76ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    /* Initialize samples */
77ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    int nn;
78ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    for (nn = 0; nn < SAMPLE_SIZE; nn++) {
79ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        ta->sample[nn] = (short)(((nn % (SAMPLE_SIZE/4))*65536/(SAMPLE_SIZE/4)) & 0xffff);
80ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    }
81ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
82ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    AUD_set_active_out(ta->voice, 1);
83ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    return 0;
84ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner}
85ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
86ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turnerstatic TestAudio*  testAudio;
87ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner
88ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turnerint
89ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turnerandroid_audio_test_start_out(void)
90ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner{
91ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    if (!testAudio) {
92ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        testAudio = malloc(sizeof(*testAudio));
93ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        if (testAudio_init(testAudio) < 0) {
94ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner            free(testAudio);
95ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner            testAudio = NULL;
96ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner            fprintf(stderr, "Could not start audio test!\n");
97ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner            return -1;
98ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        } else {
99ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner            printf("Audio test started!\n");
100ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner        }
101ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    }
102ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner    return 0;
103ca29fbbb188a1aab9b69776d5dc6bc3e7f812a0aDavid 'Digit' Turner}
104