| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| /* |
| * BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data |
| * and saves them to disk. The files are stored in the path specified in BUFLOG_BASE_PATH and |
| * are named following this format: |
| * YYYYMMDDHHMMSS_id_format_channels_samplingrate.raw |
| * |
| * Normally we strip BUFLOG dumps from release builds. |
| * You can modify this (for example with "#define BUFLOG_NDEBUG 0" |
| * at the top of your source file) to change that behavior. |
| * |
| * usage: |
| * - Add this to the top of the source file you want to debug: |
| * #define BUFLOG_NDEBUG 0 |
| * #include "BufLog.h" |
| * |
| * - dump an audio buffer |
| * BUFLOG(buff_id, buff_tag, format, channels, sampling_rate, max_bytes, buff_pointer, buff_size); |
| * |
| * buff_id: int [0:15] buffer id. If a buffer doesn't exist, it is created the first time. |
| * buff_tag: char* string tag used on stream filename and logs |
| * format: int Audio format (audio_format_t see audio.h) |
| * channels: int Channel Count |
| * sampling_rate: int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc |
| * max_bytes: int [0 or positive number] |
| * Maximum size of the file (in bytes) to be output. |
| * If the value is 0, no limit. |
| * buff_pointer: void * Pointer to audio buffer. |
| * buff_size: int Size (in bytes) of the current audio buffer to be stored. |
| * |
| * |
| * Example usage: |
| * int format = mConfig.outputCfg.format; |
| * int channels = audio_channel_count_from_out_mask(mConfig.outputCfg.channels); |
| * int samplingRate = mConfig.outputCfg.samplingRate; |
| * int frameCount = mConfig.outputCfg.buffer.frameCount; |
| * int frameSize = audio_bytes_per_sample((audio_format_t)format) * channels; |
| * int buffSize = frameCount * frameSize; |
| * long maxBytes = 10 * samplingRate * frameSize; //10 seconds max |
| * BUFLOG(11, "loudnes_enhancer_out", format, channels, samplingRate, maxBytes, |
| * mConfig.outputCfg.buffer.raw, buffSize); |
| * |
| * Other macros: |
| * BUFLOG_EXISTS returns true if there is an instance of BufLog |
| * |
| * BUFLOG_RESET If an instance of BufLog exists, it stops the capture and closes all |
| * streams. |
| * If a new call to BUFLOG(..) is done, new streams are created. |
| */ |
| |
| #ifndef BUFLOG_NDEBUG |
| #ifdef NDEBUG |
| #define BUFLOG_NDEBUG 1 |
| #else |
| #define BUFLOG_NDEBUG 0 |
| #endif |
| #endif |
| |
| /* |
| * Simplified macro to send a buffer. |
| */ |
| #ifndef BUFLOG |
| #define __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \ |
| BufLogSingleton::instance()->write(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, \ |
| BUF, SIZE) |
| #if BUFLOG_NDEBUG |
| #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \ |
| do { if (0) { } } while (0) |
| #else |
| #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \ |
| __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) |
| #endif |
| #endif |
| |
| #ifndef BUFLOG_EXISTS |
| #define BUFLOG_EXISTS BufLogSingleton::instanceExists() |
| #endif |
| |
| #ifndef BUFLOG_RESET |
| #define BUFLOG_RESET do { if (BufLogSingleton::instanceExists()) { \ |
| BufLogSingleton::instance()->reset(); } } while (0) |
| #endif |
| |
| #include <mutex> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <sys/types.h> |
| |
| //BufLog configuration |
| #define BUFLOGSTREAM_MAX_TAGSIZE 32 |
| #define BUFLOG_BASE_PATH "/data/misc/audioserver" |
| #define BUFLOG_MAX_PATH_SIZE 300 |
| |
| namespace android { |
| |
| class BufLogStream { |
| public: |
| BufLogStream(unsigned int id, |
| const char *tag, |
| unsigned int format, |
| unsigned int channels, |
| unsigned int samplingRate, |
| size_t maxBytes); |
| ~BufLogStream(); |
| |
| // write buffer to stream |
| // buf: pointer to buffer |
| // size: number of bytes to write |
| size_t write(const void *buf, size_t size); |
| |
| // pause/resume stream |
| // pause: true = paused, false = not paused |
| // return value: previous state of stream (paused or not). |
| bool setPause(bool pause); |
| |
| // will stop the stream and close any open file |
| // the stream can't be reopen. Instead, a new stream (and file) should be created. |
| void finalize(); |
| |
| private: |
| const unsigned int mId; |
| const unsigned int mFormat; |
| const unsigned int mChannels; |
| const unsigned int mSamplingRate; |
| const size_t mMaxBytes; |
| char mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1]; // const, set in ctor. |
| |
| mutable std::mutex mLock; |
| bool mPaused = false; |
| size_t mByteCount = 0; |
| FILE *mFile; // set in ctor |
| |
| void closeStream_l(); |
| }; |
| |
| class BufLog { |
| public: |
| ~BufLog(); |
| |
| // streamid: int [0:BUFLOG_MAXSTREAMS-1] buffer id. |
| // If a buffer doesn't exist, it is created the first time is referenced |
| // tag: char* string tag used on stream filename and logs |
| // format: int Audio format (audio_format_t see audio.h) |
| // channels: int Channel Count |
| // samplingRate: int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc |
| // maxBytes: int [0 or positive number] |
| // Maximum size of the file (in bytes) to be output. |
| // If the value is 0, no limit. |
| // size: int Size (in bytes) of the current audio buffer to be written. |
| // buf: void * Pointer to audio buffer. |
| size_t write(int streamid, |
| const char *tag, |
| int format, |
| int channels, |
| int samplingRate, |
| size_t maxBytes, |
| const void *buf, |
| size_t size); |
| |
| // reset will stop and close all active streams, thus finalizing any open file. |
| // New streams will be created if write() is called again. |
| void reset(); |
| |
| protected: |
| static constexpr size_t BUFLOG_MAXSTREAMS = 16; |
| mutable std::mutex mLock; |
| BufLogStream *mStreams[BUFLOG_MAXSTREAMS]{}; |
| }; |
| |
| class BufLogSingleton { |
| public: |
| static BufLog *instance(); |
| static bool instanceExists(); |
| |
| private: |
| static void initOnce(); |
| static BufLog *mInstance; |
| }; |
| |
| } // namespace android |