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