1da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent/*
2da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Copyright (C) 2010 The Android Open Source Project
3da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *
4da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * you may not use this file except in compliance with the License.
6da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * You may obtain a copy of the License at
7da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *
8da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *
10da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Unless required by applicable law or agreed to in writing, software
11da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * See the License for the specific language governing permissions and
14da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * limitations under the License.
15da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent */
16da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
17da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#ifndef ANDROID_MEDIA_VISUALIZER_H
18da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#define ANDROID_MEDIA_VISUALIZER_H
19da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
20da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <media/AudioEffect.h>
216d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent#include <audio_effects/effect_visualizer.h>
22da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <string.h>
23da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
24da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent/**
25da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * The Visualizer class enables application to retrieve part of the currently playing audio for
26da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * visualization purpose. It is not an audio recording interface and only returns partial and low
27da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
28da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * of the visualizer requires the permission android.permission.RECORD_AUDIO.
29da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * The audio session ID passed to the constructor indicates which audio content should be
30da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * visualized:
31da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * - If the session is 0, the audio output mix is visualized
32da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack
33da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *   using this audio session is visualized
34da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Two types of representation of audio content can be captured:
35da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method
36da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * - Frequency data: 8-bit magnitude FFT by using the getFft() method
37da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *
38da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * The length of the capture can be retrieved or specified by calling respectively
39da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT
40da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * is half of the specified capture size but both sides of the spectrum are returned yielding in a
41da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * number of bytes equal to the capture size. The capture size must be a power of 2 in the range
42da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * returned by getMinCaptureSize() and getMaxCaptureSize().
43da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * In addition to the polling capture mode, a callback mode is also available by installing a
44da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * callback function by use of the setCaptureCallBack() method. The rate at which the callback
45da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * is called as well as the type of data returned is specified.
46da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method.
47da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * When data capture is not needed any more, the Visualizer should be disabled.
48da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent */
49da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
50da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
51da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentnamespace android {
52da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
53da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// ----------------------------------------------------------------------------
54da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
55da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentclass Visualizer: public AudioEffect {
56da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentpublic:
57da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
58da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    enum callback_flags {
59da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        CAPTURE_WAVEFORM = 0x00000001,  // capture callback returns a PCM wave form
60da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        CAPTURE_FFT = 0x00000002,       // apture callback returns a frequency representation
61da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        CAPTURE_CALL_JAVA = 0x00000004  // the callback thread can call java
62da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    };
63da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
64da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
65da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    /* Constructor.
66da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent     * See AudioEffect constructor for details on parameters.
67da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent     */
68da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                        Visualizer(int32_t priority = 0,
69a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten                                   effect_callback_t cbf = NULL,
70a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten                                   void* user = NULL,
71da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                                   int sessionId = 0);
72da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
73da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                        ~Visualizer();
74da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
75da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    virtual status_t    setEnabled(bool enabled);
76da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
77da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // maximum capture size in samples
78da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; }
79da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // minimum capture size in samples
80da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; }
81da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // maximum capture rate in millihertz
82da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; }
83da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
84da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // callback used to return periodic PCM or FFT captures to the application. Either one or both
85da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // types of data are returned (PCM and FFT) according to flags indicated when installing the
86da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // callback. When a type of data is not present, the corresponding size (waveformSize or
87da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // fftSize) is 0.
88da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    typedef void (*capture_cbk_t)(void* user,
89da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                                    uint32_t waveformSize,
90da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                                    uint8_t *waveform,
91da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                                    uint32_t fftSize,
92da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                                    uint8_t *fft,
93da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                                    uint32_t samplingrate);
94da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
95da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // install a callback to receive periodic captures. The capture rate is specified in milliHertz
96da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // and the capture format is according to flags  (see callback_flags).
97da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate);
98da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
99da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // set the capture size capture size must be a power of two in the range
100da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN]
101da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // must be called when the visualizer is not enabled
102da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t setCaptureSize(uint32_t size);
103da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t getCaptureSize() { return mCaptureSize; }
104da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
105da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // returns the capture rate indicated when installing the callback
106da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t getCaptureRate() { return mCaptureRate; }
107da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
108da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // returns the sampling rate of the audio being captured
109da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t getSamplingRate() { return mSampleRate; }
110da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
1113476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    // set the way volume affects the captured data
1123476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    // mode must one of VISUALIZER_SCALING_MODE_NORMALIZED,
1133476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    //  VISUALIZER_SCALING_MODE_AS_PLAYED
1143476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    status_t setScalingMode(uint32_t mode);
1153476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    uint32_t getScalingMode() { return mScalingMode; }
1163476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
117da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
118da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // getCaptureSize()
119da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t getWaveForm(uint8_t *waveform);
120da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
121da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // return a capture in FFT 8 bit signed format. The size of the capture is equal to
122da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum
123da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    // are returned
124da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t getFft(uint8_t *fft);
125da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
1263476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Triviprotected:
1273476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    // from IEffectClient
1283476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    virtual void controlStatusChanged(bool controlGranted);
1293476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
130da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentprivate:
131da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
132da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    static const uint32_t CAPTURE_RATE_MAX = 20000;
133da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    static const uint32_t CAPTURE_RATE_DEF = 10000;
134da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX;
135da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
136da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    /* internal class to handle the callback */
137da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    class CaptureThread : public Thread
138da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    {
139da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    public:
140da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava = false);
141da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
142da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    private:
143da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        friend class Visualizer;
144da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        virtual bool        threadLoop();
145da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        Visualizer& mReceiver;
146da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        Mutex       mLock;
147da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint32_t mSleepTimeUs;
148da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    };
149da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
150da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t doFft(uint8_t *fft, uint8_t *waveform);
151da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    void periodicCapture();
152da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t initCaptureSize();
153da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
154a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex mCaptureLock;
155da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t mCaptureRate;
156da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t mCaptureSize;
157da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t mSampleRate;
1583476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    uint32_t mScalingMode;
159da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    capture_cbk_t mCaptureCallBack;
160da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    void *mCaptureCbkUser;
161da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    sp<CaptureThread> mCaptureThread;
162da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t mCaptureFlags;
163da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent};
164da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
165da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
166da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; // namespace android
167da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
168da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#endif // ANDROID_MEDIA_VISUALIZER_H
169