1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*ec779b8eSAndroid Build Coastguard Worker * 4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*ec779b8eSAndroid Build Coastguard Worker * 8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*ec779b8eSAndroid Build Coastguard Worker * 10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License. 15*ec779b8eSAndroid Build Coastguard Worker */ 16*ec779b8eSAndroid Build Coastguard Worker 17*ec779b8eSAndroid Build Coastguard Worker #pragma once 18*ec779b8eSAndroid Build Coastguard Worker 19*ec779b8eSAndroid Build Coastguard Worker /* 20*ec779b8eSAndroid Build Coastguard Worker * BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data 21*ec779b8eSAndroid Build Coastguard Worker * and saves them to disk. The files are stored in the path specified in BUFLOG_BASE_PATH and 22*ec779b8eSAndroid Build Coastguard Worker * are named following this format: 23*ec779b8eSAndroid Build Coastguard Worker * YYYYMMDDHHMMSS_id_format_channels_samplingrate.raw 24*ec779b8eSAndroid Build Coastguard Worker * 25*ec779b8eSAndroid Build Coastguard Worker * Normally we strip BUFLOG dumps from release builds. 26*ec779b8eSAndroid Build Coastguard Worker * You can modify this (for example with "#define BUFLOG_NDEBUG 0" 27*ec779b8eSAndroid Build Coastguard Worker * at the top of your source file) to change that behavior. 28*ec779b8eSAndroid Build Coastguard Worker * 29*ec779b8eSAndroid Build Coastguard Worker * usage: 30*ec779b8eSAndroid Build Coastguard Worker * - Add this to the top of the source file you want to debug: 31*ec779b8eSAndroid Build Coastguard Worker * #define BUFLOG_NDEBUG 0 32*ec779b8eSAndroid Build Coastguard Worker * #include "BufLog.h" 33*ec779b8eSAndroid Build Coastguard Worker * 34*ec779b8eSAndroid Build Coastguard Worker * - dump an audio buffer 35*ec779b8eSAndroid Build Coastguard Worker * BUFLOG(buff_id, buff_tag, format, channels, sampling_rate, max_bytes, buff_pointer, buff_size); 36*ec779b8eSAndroid Build Coastguard Worker * 37*ec779b8eSAndroid Build Coastguard Worker * buff_id: int [0:15] buffer id. If a buffer doesn't exist, it is created the first time. 38*ec779b8eSAndroid Build Coastguard Worker * buff_tag: char* string tag used on stream filename and logs 39*ec779b8eSAndroid Build Coastguard Worker * format: int Audio format (audio_format_t see audio.h) 40*ec779b8eSAndroid Build Coastguard Worker * channels: int Channel Count 41*ec779b8eSAndroid Build Coastguard Worker * sampling_rate: int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc 42*ec779b8eSAndroid Build Coastguard Worker * max_bytes: int [0 or positive number] 43*ec779b8eSAndroid Build Coastguard Worker * Maximum size of the file (in bytes) to be output. 44*ec779b8eSAndroid Build Coastguard Worker * If the value is 0, no limit. 45*ec779b8eSAndroid Build Coastguard Worker * buff_pointer: void * Pointer to audio buffer. 46*ec779b8eSAndroid Build Coastguard Worker * buff_size: int Size (in bytes) of the current audio buffer to be stored. 47*ec779b8eSAndroid Build Coastguard Worker * 48*ec779b8eSAndroid Build Coastguard Worker * 49*ec779b8eSAndroid Build Coastguard Worker * Example usage: 50*ec779b8eSAndroid Build Coastguard Worker * int format = mConfig.outputCfg.format; 51*ec779b8eSAndroid Build Coastguard Worker * int channels = audio_channel_count_from_out_mask(mConfig.outputCfg.channels); 52*ec779b8eSAndroid Build Coastguard Worker * int samplingRate = mConfig.outputCfg.samplingRate; 53*ec779b8eSAndroid Build Coastguard Worker * int frameCount = mConfig.outputCfg.buffer.frameCount; 54*ec779b8eSAndroid Build Coastguard Worker * int frameSize = audio_bytes_per_sample((audio_format_t)format) * channels; 55*ec779b8eSAndroid Build Coastguard Worker * int buffSize = frameCount * frameSize; 56*ec779b8eSAndroid Build Coastguard Worker * long maxBytes = 10 * samplingRate * frameSize; //10 seconds max 57*ec779b8eSAndroid Build Coastguard Worker * BUFLOG(11, "loudnes_enhancer_out", format, channels, samplingRate, maxBytes, 58*ec779b8eSAndroid Build Coastguard Worker * mConfig.outputCfg.buffer.raw, buffSize); 59*ec779b8eSAndroid Build Coastguard Worker * 60*ec779b8eSAndroid Build Coastguard Worker * Other macros: 61*ec779b8eSAndroid Build Coastguard Worker * BUFLOG_EXISTS returns true if there is an instance of BufLog 62*ec779b8eSAndroid Build Coastguard Worker * 63*ec779b8eSAndroid Build Coastguard Worker * BUFLOG_RESET If an instance of BufLog exists, it stops the capture and closes all 64*ec779b8eSAndroid Build Coastguard Worker * streams. 65*ec779b8eSAndroid Build Coastguard Worker * If a new call to BUFLOG(..) is done, new streams are created. 66*ec779b8eSAndroid Build Coastguard Worker */ 67*ec779b8eSAndroid Build Coastguard Worker 68*ec779b8eSAndroid Build Coastguard Worker #ifndef BUFLOG_NDEBUG 69*ec779b8eSAndroid Build Coastguard Worker #ifdef NDEBUG 70*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG_NDEBUG 1 71*ec779b8eSAndroid Build Coastguard Worker #else 72*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG_NDEBUG 0 73*ec779b8eSAndroid Build Coastguard Worker #endif 74*ec779b8eSAndroid Build Coastguard Worker #endif 75*ec779b8eSAndroid Build Coastguard Worker 76*ec779b8eSAndroid Build Coastguard Worker /* 77*ec779b8eSAndroid Build Coastguard Worker * Simplified macro to send a buffer. 78*ec779b8eSAndroid Build Coastguard Worker */ 79*ec779b8eSAndroid Build Coastguard Worker #ifndef BUFLOG 80*ec779b8eSAndroid Build Coastguard Worker #define __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \ 81*ec779b8eSAndroid Build Coastguard Worker BufLogSingleton::instance()->write(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, \ 82*ec779b8eSAndroid Build Coastguard Worker BUF, SIZE) 83*ec779b8eSAndroid Build Coastguard Worker #if BUFLOG_NDEBUG 84*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \ 85*ec779b8eSAndroid Build Coastguard Worker do { if (0) { } } while (0) 86*ec779b8eSAndroid Build Coastguard Worker #else 87*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \ 88*ec779b8eSAndroid Build Coastguard Worker __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) 89*ec779b8eSAndroid Build Coastguard Worker #endif 90*ec779b8eSAndroid Build Coastguard Worker #endif 91*ec779b8eSAndroid Build Coastguard Worker 92*ec779b8eSAndroid Build Coastguard Worker #ifndef BUFLOG_EXISTS 93*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG_EXISTS BufLogSingleton::instanceExists() 94*ec779b8eSAndroid Build Coastguard Worker #endif 95*ec779b8eSAndroid Build Coastguard Worker 96*ec779b8eSAndroid Build Coastguard Worker #ifndef BUFLOG_RESET 97*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG_RESET do { if (BufLogSingleton::instanceExists()) { \ 98*ec779b8eSAndroid Build Coastguard Worker BufLogSingleton::instance()->reset(); } } while (0) 99*ec779b8eSAndroid Build Coastguard Worker #endif 100*ec779b8eSAndroid Build Coastguard Worker 101*ec779b8eSAndroid Build Coastguard Worker #include <mutex> 102*ec779b8eSAndroid Build Coastguard Worker #include <stdint.h> 103*ec779b8eSAndroid Build Coastguard Worker #include <stdio.h> 104*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h> 105*ec779b8eSAndroid Build Coastguard Worker 106*ec779b8eSAndroid Build Coastguard Worker //BufLog configuration 107*ec779b8eSAndroid Build Coastguard Worker #define BUFLOGSTREAM_MAX_TAGSIZE 32 108*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG_BASE_PATH "/data/misc/audioserver" 109*ec779b8eSAndroid Build Coastguard Worker #define BUFLOG_MAX_PATH_SIZE 300 110*ec779b8eSAndroid Build Coastguard Worker 111*ec779b8eSAndroid Build Coastguard Worker namespace android { 112*ec779b8eSAndroid Build Coastguard Worker 113*ec779b8eSAndroid Build Coastguard Worker class BufLogStream { 114*ec779b8eSAndroid Build Coastguard Worker public: 115*ec779b8eSAndroid Build Coastguard Worker BufLogStream(unsigned int id, 116*ec779b8eSAndroid Build Coastguard Worker const char *tag, 117*ec779b8eSAndroid Build Coastguard Worker unsigned int format, 118*ec779b8eSAndroid Build Coastguard Worker unsigned int channels, 119*ec779b8eSAndroid Build Coastguard Worker unsigned int samplingRate, 120*ec779b8eSAndroid Build Coastguard Worker size_t maxBytes); 121*ec779b8eSAndroid Build Coastguard Worker ~BufLogStream(); 122*ec779b8eSAndroid Build Coastguard Worker 123*ec779b8eSAndroid Build Coastguard Worker // write buffer to stream 124*ec779b8eSAndroid Build Coastguard Worker // buf: pointer to buffer 125*ec779b8eSAndroid Build Coastguard Worker // size: number of bytes to write 126*ec779b8eSAndroid Build Coastguard Worker size_t write(const void *buf, size_t size); 127*ec779b8eSAndroid Build Coastguard Worker 128*ec779b8eSAndroid Build Coastguard Worker // pause/resume stream 129*ec779b8eSAndroid Build Coastguard Worker // pause: true = paused, false = not paused 130*ec779b8eSAndroid Build Coastguard Worker // return value: previous state of stream (paused or not). 131*ec779b8eSAndroid Build Coastguard Worker bool setPause(bool pause); 132*ec779b8eSAndroid Build Coastguard Worker 133*ec779b8eSAndroid Build Coastguard Worker // will stop the stream and close any open file 134*ec779b8eSAndroid Build Coastguard Worker // the stream can't be reopen. Instead, a new stream (and file) should be created. 135*ec779b8eSAndroid Build Coastguard Worker void finalize(); 136*ec779b8eSAndroid Build Coastguard Worker 137*ec779b8eSAndroid Build Coastguard Worker private: 138*ec779b8eSAndroid Build Coastguard Worker const unsigned int mId; 139*ec779b8eSAndroid Build Coastguard Worker const unsigned int mFormat; 140*ec779b8eSAndroid Build Coastguard Worker const unsigned int mChannels; 141*ec779b8eSAndroid Build Coastguard Worker const unsigned int mSamplingRate; 142*ec779b8eSAndroid Build Coastguard Worker const size_t mMaxBytes; 143*ec779b8eSAndroid Build Coastguard Worker char mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1]; // const, set in ctor. 144*ec779b8eSAndroid Build Coastguard Worker 145*ec779b8eSAndroid Build Coastguard Worker mutable std::mutex mLock; 146*ec779b8eSAndroid Build Coastguard Worker bool mPaused = false; 147*ec779b8eSAndroid Build Coastguard Worker size_t mByteCount = 0; 148*ec779b8eSAndroid Build Coastguard Worker FILE *mFile; // set in ctor 149*ec779b8eSAndroid Build Coastguard Worker 150*ec779b8eSAndroid Build Coastguard Worker void closeStream_l(); 151*ec779b8eSAndroid Build Coastguard Worker }; 152*ec779b8eSAndroid Build Coastguard Worker 153*ec779b8eSAndroid Build Coastguard Worker class BufLog { 154*ec779b8eSAndroid Build Coastguard Worker public: 155*ec779b8eSAndroid Build Coastguard Worker ~BufLog(); 156*ec779b8eSAndroid Build Coastguard Worker 157*ec779b8eSAndroid Build Coastguard Worker // streamid: int [0:BUFLOG_MAXSTREAMS-1] buffer id. 158*ec779b8eSAndroid Build Coastguard Worker // If a buffer doesn't exist, it is created the first time is referenced 159*ec779b8eSAndroid Build Coastguard Worker // tag: char* string tag used on stream filename and logs 160*ec779b8eSAndroid Build Coastguard Worker // format: int Audio format (audio_format_t see audio.h) 161*ec779b8eSAndroid Build Coastguard Worker // channels: int Channel Count 162*ec779b8eSAndroid Build Coastguard Worker // samplingRate: int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc 163*ec779b8eSAndroid Build Coastguard Worker // maxBytes: int [0 or positive number] 164*ec779b8eSAndroid Build Coastguard Worker // Maximum size of the file (in bytes) to be output. 165*ec779b8eSAndroid Build Coastguard Worker // If the value is 0, no limit. 166*ec779b8eSAndroid Build Coastguard Worker // size: int Size (in bytes) of the current audio buffer to be written. 167*ec779b8eSAndroid Build Coastguard Worker // buf: void * Pointer to audio buffer. 168*ec779b8eSAndroid Build Coastguard Worker size_t write(int streamid, 169*ec779b8eSAndroid Build Coastguard Worker const char *tag, 170*ec779b8eSAndroid Build Coastguard Worker int format, 171*ec779b8eSAndroid Build Coastguard Worker int channels, 172*ec779b8eSAndroid Build Coastguard Worker int samplingRate, 173*ec779b8eSAndroid Build Coastguard Worker size_t maxBytes, 174*ec779b8eSAndroid Build Coastguard Worker const void *buf, 175*ec779b8eSAndroid Build Coastguard Worker size_t size); 176*ec779b8eSAndroid Build Coastguard Worker 177*ec779b8eSAndroid Build Coastguard Worker // reset will stop and close all active streams, thus finalizing any open file. 178*ec779b8eSAndroid Build Coastguard Worker // New streams will be created if write() is called again. 179*ec779b8eSAndroid Build Coastguard Worker void reset(); 180*ec779b8eSAndroid Build Coastguard Worker 181*ec779b8eSAndroid Build Coastguard Worker protected: 182*ec779b8eSAndroid Build Coastguard Worker static constexpr size_t BUFLOG_MAXSTREAMS = 16; 183*ec779b8eSAndroid Build Coastguard Worker mutable std::mutex mLock; 184*ec779b8eSAndroid Build Coastguard Worker BufLogStream *mStreams[BUFLOG_MAXSTREAMS]{}; 185*ec779b8eSAndroid Build Coastguard Worker }; 186*ec779b8eSAndroid Build Coastguard Worker 187*ec779b8eSAndroid Build Coastguard Worker class BufLogSingleton { 188*ec779b8eSAndroid Build Coastguard Worker public: 189*ec779b8eSAndroid Build Coastguard Worker static BufLog *instance(); 190*ec779b8eSAndroid Build Coastguard Worker static bool instanceExists(); 191*ec779b8eSAndroid Build Coastguard Worker 192*ec779b8eSAndroid Build Coastguard Worker private: 193*ec779b8eSAndroid Build Coastguard Worker static void initOnce(); 194*ec779b8eSAndroid Build Coastguard Worker static BufLog *mInstance; 195*ec779b8eSAndroid Build Coastguard Worker }; 196*ec779b8eSAndroid Build Coastguard Worker 197*ec779b8eSAndroid Build Coastguard Worker } // namespace android 198