⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spectral.c

📁 g729 coding ipaddressing
💻 C
📖 第 1 页 / 共 2 页
字号:

/*

				Audio Monitor Display
	 
*/

#include "netfone.h"

static int nbands = 128;				// Frequency bands to plot
static int fftsize = 512;				// Size of FFT
static int logscale = TRUE;				// Show log of intensity ?
static int logfreq = FALSE;				// Plot log of frequency ?

static short *samples = NULL;			// Audio sample buffer
static unsigned char *sourceSpectrum = NULL;	// Source of samples table
static int samps_in_buffer = 0;			// Samples in buffer
static HBITMAP easel = NULL;			// Bitmap to refresh spectrum display
static HBITMAP weasel = NULL;			// Bitmap to refresh envelope display

static double cEnergy = 0.0;			// Average energy of samples in buffer
static double mEnergy = 0.0;			// Maximum energy in buffer
#ifdef _DEBUG
static int aEnergy = 0;					// Unscaled energy for debugging
#endif
static int logEnergy = FALSE;			// Show log of energy ?
static int noiseFloor = 0;				// Noise floor
static COLORREF ceColour = RGB(0, 255, 0);	// Current input source tagged colour
static BOOL spectrumChanged = TRUE;		// Spectrum display mode changed

static double *pspectrum = NULL;		// Computed power spectrum
static double pscale = 1.0;				// Maximum value in power spectrum

#define PSMOOTH		   0.001			// Smoothing factor for spectrum scale
static double escale = 0.0;				// Exponentially smoothed power spectrum scale
static int epposx = 0;					// Energy plot position

#define M_E			   2.7182818284590452354

#define WM_UPDATE_SPECTRUM	(WM_USER + 1000)

BOOL spectrumBarGraph = TRUE;			// Plot spectrum as bar chart, equaliser style ?
BOOL spectrumVoicePrint = FALSE;		// Plot spectrum as horizontal "waterfall" ?
BOOL spectrumTransmitOnly = FALSE;		// Show transmitted audio only ?
BOOL spectrumReceiveOnly = FALSE;		// Show received audio only ?
BOOL spectrumMaxEnergy = FALSE;			// Plot maximum energy ?

static BOOL paintingSpectrum = FALSE;	// Busy painting spectrum ?
static int sgposx = 0;					// Spectrogram bar position

#define SPECTRUM_INTERVAL	0			// Spectrum update interval in milliseconds
static DWORD nextSpectrumTime = 0;		// Time for next spectrum ?

//	PAINTENERGY  --  Paint the energy display in its canvas

static void paintEnergy(HWND canvas)
{
	HDC hdc = GetDC(canvas), hdca = NULL;
	RECT r;
	HPEN pen;
	HBITMAP oe;
	int width, height, dy;
	double yscale = escale;

	paintingSpectrum = TRUE;
//	InvalidateRect(canvas, NULL, TRUE);
//	UpdateWindow(canvas);

	GetClientRect(canvas, &r);
	r.left++;
	r.top++;
	r.right--;
	r.bottom--;
	width = r.right - r.left;
	height = r.bottom - r.top;

	hdca = CreateCompatibleDC(hdc);
	oe = SelectObject(hdca, weasel);

	dy = (int) ((height / 2) * (spectrumMaxEnergy ? mEnergy : cEnergy));

	pen = (HPEN) SelectObject(hdca, GetStockObject(BLACK_PEN));
	MoveToEx(hdca, r.left + epposx, r.top, NULL);
	LineTo(hdca, r.left + epposx, r.top + ((height / 2) - dy));
	MoveToEx(hdca, r.left + epposx, r.bottom - ((height / 2) - dy), NULL);
	LineTo(hdca, r.left + epposx, r.bottom);
	SelectObject(hdca, pen);

	if (dy == 0) {
		SetPixel(hdca, r.left + epposx, r.top + (height / 2), ceColour);
	} else {
		pen = CreatePen(PS_SOLID, 1, ceColour);
		pen = (HPEN) SelectObject(hdca, pen);
		MoveToEx(hdca, r.left + epposx, r.top + ((height / 2) - dy), NULL);
		LineTo(hdca, r.left + epposx, r.bottom - ((height / 2) - dy));
		DeleteObject(SelectObject(hdca, pen));
		if (mEnergy >= 1) {
/*
			SetPixel(hdca, r.left + epposx, r.top, RGB(255, 0, 0));
			SetPixel(hdca, r.left + epposx, r.top + (height - 1), RGB(255, 0, 0));
			SetPixel(hdca, r.left + epposx, r.top + 1, RGB(255, 0, 0));
			SetPixel(hdca, r.left + epposx, r.top + (height - 2), RGB(255, 0, 0));
*/
/*
			pen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
			pen = (HPEN) SelectObject(hdca, pen);
			MoveToEx(hdca, r.left + epposx, r.top + ((height / 2) - 3), NULL);
			LineTo(hdca, r.left + epposx, r.bottom - ((height / 2) - 3));
			DeleteObject(SelectObject(hdca, pen));
*/
			pen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
			pen = (HPEN) SelectObject(hdca, pen);
			MoveToEx(hdca, r.left + epposx, r.top, NULL);
			LineTo(hdca, r.left + epposx, r.top + 3);
			MoveToEx(hdca, r.left + epposx, r.bottom - 3, NULL);
			LineTo(hdca, r.left + epposx, r.bottom);
			DeleteObject(SelectObject(hdca, pen));
		}
	}

	epposx++;
	if (epposx >= width) {
		epposx = 0;
	}

	//	Paint cursor over next column

	pen = (HPEN) SelectObject(hdca, GetStockObject(WHITE_PEN));
	MoveToEx(hdca, r.left + epposx, r.top, NULL);
	LineTo(hdca, r.left + epposx, r.bottom);
	SelectObject(hdca, pen);

	SelectObject(hdca, oe);
	DeleteDC(hdca);
	ReleaseDC(canvas, hdc);
	paintingSpectrum = FALSE;
}

//	PAINTSPECTRUM  --  Paint the spectrum display in the canvas

static BOOL disableShown = FALSE;

static void paintSpectrum(HWND canvas)
{
	HDC hdc = GetDC(canvas), hdca = NULL;
	RECT r;
	HBRUSH br;
	HPEN pen;
	HBITMAP oe;
	int i, width, height;
	double yscale = escale;

	if (logscale) {
		yscale = log(M_E + escale) - 1;
	}

	paintingSpectrum = TRUE;

	GetClientRect(canvas, &r);

	r.left++;
	r.top++;
	r.right--;
	r.bottom--;

	width = r.right - r.left;
	height = r.bottom - r.top;

	hdca = CreateCompatibleDC(hdc);
	oe = SelectObject(hdca, easel);
	disableShown = FALSE;
	if (spectrumChanged) {
		br = (HBRUSH) SelectObject(hdca, GetStockObject(GRAY_BRUSH));
		pen = SelectObject(hdca, GetStockObject(NULL_PEN));
		Rectangle(hdca, r.left - 1, r.top - 1, width + 2, height + 2);
		SelectObject(hdca, pen);
		SelectObject(hdca, br);
		spectrumChanged = FALSE;
	}

	/*	Bar graph display (like multiband equaliser).  As the
		whole display changes every sample we paint off-screen
		and blast BLT to the display pane.  */

	if (spectrumBarGraph && (easel != NULL)) {
		br = (HBRUSH) SelectObject(hdca, GetStockObject(GRAY_BRUSH));
		pen = SelectObject(hdca, GetStockObject(NULL_PEN));
		Rectangle(hdca, r.left, r.top, width, height);
		SelectObject(hdca, pen);
		SelectObject(hdca, br);

		pen = (HPEN) SelectObject(hdca, GetStockObject(BLACK_PEN));

		for (i = 0; i < nbands; i++) {
			int barx0 = (i * width) / nbands,
				barx1 = ((i + 1) * width) / nbands,
				bary = (int) (((logscale ? (log(M_E + pspectrum[i]) - 1) : pspectrum[i]) * height) / yscale),
				cr, cg, cb;

			cr = (255 * ((nbands - 1) - i)) / (nbands - 1);
			cg = (((nbands / 2) - abs(i - (nbands / 2))) * 255) / (nbands / 2);
			cb = (255 * i) / (nbands - 1);
			br = CreateSolidBrush(RGB(cr, cg, cb));
			br = (HBRUSH) SelectObject(hdca, br);
			Rectangle(hdca, r.left + barx0, r.bottom - bary, r.left + barx1, r.bottom);
			DeleteObject(SelectObject(hdca, br));
			DeleteObject(SelectObject(hdca, pen));
		}
	}

	/*	Spectrogram display.  This is like the "waterfall" sonar display
		on an SSN, but scrolls horizontally rather than vertically.  */

#define BLACKBIAS	100
	else if (spectrumVoicePrint && (easel != NULL)) {
		if (logfreq) {
			int j, y0, y1;
			double lspectrum[256];
			double lscale = log(nbands + M_E) - 1;

			memset(lspectrum, 0, sizeof(lspectrum));
			for (i = 0; i < nbands; i++) {
				y0 = (int) (nbands * (log(i + M_E) - 1) / lscale);
				y1 = (int) (nbands * (log((i + 1) + M_E) - 1) / lscale);
				for (j = y0; j < y1; j++) {
					lspectrum[j] += pspectrum[i];
				}
			}
			memcpy(pspectrum, lspectrum, nbands * sizeof(double));
		}
		for (i = 0; i < nbands; i++) {
			int y0 = (i * height) / nbands,
				y1 = (i == (nbands - 1)) ? height : (((i + 1) * height) / nbands),
				cindex = (int) ((((logscale ? (log(M_E + pspectrum[i]) - 1) : pspectrum[i])) / yscale) * 255),
				cr, cg, cb;

/*
			if (logfreq) {
				y0 = (int) (height * (log(y0 + M_E) - 1) / yscale);
				y1 = (int) (height * (log(y1 + M_E) - 1) / yscale);
				if (i == (nbands - 1)) {
					y1 = height;
				}
			}
*/

			if (cindex < BLACKBIAS) {
				cr = cg = cb = 0;
			} else {
				cindex = 255 - (((cindex - BLACKBIAS) * 255) / (255 - BLACKBIAS));
#ifndef ZZZ
				cr = (255 * (255 - cindex)) / 255;
				cg = ((128 - abs(cindex - 128)) * 255) / 128;
				cb = (255 * cindex) / 255;
#else
				cr = cg = cb = cindex;
#endif
			}
			pen = CreatePen(PS_SOLID, 1, RGB(cr, cg, cb));
			pen = (HPEN) SelectObject(hdca, pen);
			MoveToEx(hdca, r.left + sgposx, (r.bottom - 1) - y0, NULL);
			LineTo(hdca, r.left + sgposx, (r.bottom - 1) - y1);
			DeleteObject(SelectObject(hdca, pen));
		}
		sgposx++;
		if (sgposx >= width) {
			sgposx = 0;
		}

		//	Paint cursor over next column

		pen = (HPEN) SelectObject(hdca, GetStockObject(WHITE_PEN));
		MoveToEx(hdca, r.left + sgposx, r.top, NULL);
		LineTo(hdca, r.left + sgposx, r.bottom);
		SelectObject(hdca, pen);
	}

	//	Spectrum display disabled

	else {
		char *ds = rstring(IDS_SPEC_DISABLED);
		LOGFONT lf;
		HFONT hf, of;

		lf.lfHeight = 32;
		lf.lfWidth = 0;
		lf.lfEscapement = 0;
		lf.lfOrientation = 0; 
		lf.lfWeight = FW_BOLD;
		lf.lfItalic = FALSE;
		lf.lfUnderline = FALSE;
		lf.lfStrikeOut = FALSE; 
		lf.lfCharSet = DEFAULT_CHARSET;
		lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
		lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; 
		lf.lfQuality = DEFAULT_QUALITY;
		lf.lfPitchAndFamily = DEFAULT_PITCH;
		strcpy(lf.lfFaceName, "Arial");
		hf = CreateFontIndirect(&lf);

		if (hf != NULL) {
			of = SelectObject(hdca, hf);
		}
		SetBkMode(hdca, TRANSPARENT);
		SetTextColor(hdca, RGB(192, 192, 192));
		SetTextAlign(hdca, TA_CENTER | TA_BASELINE | TA_NOUPDATECP);
		TextOut(hdca, (r.right - r.left) / 2, (r.bottom - r.top) / 2, ds, strlen(ds));
		if (hf != NULL) {
			SelectObject(hdca, of);
			DeleteObject(hf);
		}
		disableShown = TRUE;
	}

	SelectObject(hdca, oe);
	DeleteDC(hdca);
	ReleaseDC(canvas, hdc);
	paintingSpectrum = FALSE;
}

//	CLEARCANVAS  --  Clear a display frame to a given colour

static void clearCanvas(HWND canvas, COLORREF rgb)
{
	HDC hdc = GetDC(canvas);
	RECT r;
	HBRUSH br;
	HPEN pen;

	GetClientRect(canvas, &r);
	br = CreateSolidBrush(rgb);
	br = (HBRUSH) SelectObject(hdc, br);
	pen = CreatePen(PS_SOLID, 1, rgb);
	pen = (HPEN) SelectObject(hdc, pen);
	Rectangle(hdc, r.left, r.top, r.right, r.bottom);
	DeleteObject(SelectObject(hdc, pen));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -