123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- #include "precompile.h"
- #include "audiodbmeter.h"
- #include "audiocontext.h"
- #include <math.h>
- #include <assert.h>
- #include <crtdbg.h>
- #define DB_RANGE 60.0
- #define READ_IDX (STREAM_DIR_READ-1)
- #define WRITE_IDX (STREAM_DIR_WRITE-1)
- static const float const_1_div_32768_ = 1.0f / 32768.f; /* 16 bit multiplier */
- static float ClipZeroToOne(float z)
- {
- if (z > 1.0)
- return 1.0;
- else if (z < 0.0)
- return 0.0;
- else
- return z;
- }
- static float ToDB(float v, float range)
- {
- float db;
- if (v > 0)
- db = 20 * log10(fabs(v));
- else
- db = -999;
- return ClipZeroToOne((db + range) / range);
- }
- static apr_status_t read_frame(void *self, audioframe_t *frame)
- {
- audiodbmeter_t *audiometer = CONTAINING_RECORD(self, audiodbmeter_t, base);
- apr_status_t status;
- status = audiometer->base.downstream->vtbl->read_frame(audiometer->base.downstream, frame);
- if (status == APR_SUCCESS && frame->size > 0) {
- int i;
- int frames = frame->size / 2;
- short *sptr = (short*)frame->buffer;
- float peak = 0.0;
- float rms = 0.0;
- int old;
- for (i = 0; i < frames; ++i) {
- float v = *sptr * const_1_div_32768_;
- peak = (float)max(v, peak);
- rms += (float)(v * v);
- sptr++;
- }
- rms = sqrt(rms / frames);
- rms = ToDB(rms, DB_RANGE);
- peak = ToDB(peak, DB_RANGE);
- old = audiometer->stat[READ_IDX].rms;
- audiometer->stat[READ_IDX].rms = (old * 9 + (int)(100*rms)) / 10;
- old = audiometer->stat[READ_IDX].peak;
- audiometer->stat[READ_IDX].peak = (old * 9 + (int)(100*peak)) / 10;
- }
- return APR_SUCCESS;
- }
- static apr_status_t write_frame(void *self, const audioframe_t *frame)
- {
- audiodbmeter_t *audiometer = CONTAINING_RECORD(self, audiodbmeter_t, base);
- apr_status_t status;
- status = audiometer->base.downstream->vtbl->write_frame(audiometer->base.downstream, frame);
- if (status == APR_SUCCESS && frame->size > 0) {
- int i;
- int frames = frame->size / 2;
- const short *sptr = (const short *)frame->buffer;
- float peak = 0.0;
- float rms = 0.0;
- int old;
- for (i = 0; i < frames; ++i) {
- float v = *sptr * const_1_div_32768_;
- peak = (float)max(v, peak);
- rms += (float)(v * v);
- sptr++;
- }
- rms = sqrt(rms / frames);
- rms = ToDB(rms, DB_RANGE);
- peak = ToDB(peak, DB_RANGE);
- old = audiometer->stat[WRITE_IDX].rms;
- audiometer->stat[WRITE_IDX].rms = (old * 9 + (int)(100*rms)) / 10;
- old = audiometer->stat[WRITE_IDX].peak;
- audiometer->stat[WRITE_IDX].peak = (old * 9 + (int)(100*peak)) / 10;
- }
- return APR_SUCCESS;
- }
- static audiostream_vtbl_t g_stream_vtbl = {
- &read_frame,
- &write_frame,
- };
- apr_status_t audiodbmeter_create(apr_pool_t *pool, audioengine_t *engine, audiodbmeter_t **p_audiometer)
- {
- audiodbmeter_t *audiometer;
- audiometer = apr_palloc(pool, sizeof(audiodbmeter_t));
- memset(audiometer, 0, sizeof(audiodbmeter_t));
- assert(0 == READ_IDX);
- assert(1 == WRITE_IDX);
- audiostream_init(engine, &g_stream_vtbl, &audiometer->base);
- *p_audiometer = audiometer;
- return APR_SUCCESS;
- }
- apr_status_t audiodbmeter_destroy(audiodbmeter_t *audiometer)
- {
- return APR_SUCCESS;
- }
- apr_status_t audiodbmeter_get_peak_db(audiodbmeter_t *audiometer, int direction, int *pval)
- {
- int idx = direction - 1;
- *pval = audiometer->stat[idx].peak;
- return APR_SUCCESS;
- }
- apr_status_t audiodbmeter_get_rms_db(audiodbmeter_t *audiometer, int direction, int *pval)
- {
- int idx = direction - 1;
- *pval = audiometer->stat[idx].rms;
- return APR_SUCCESS;
- }
|