Parade Series - CoreAudio Loopback

2024-04-21 10:04

本文主要是介绍Parade Series - CoreAudio Loopback,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Scenario

鉴于业务场景需要, 经过技术路径探索, 发现 comtypes 兼容性过于混乱,故而考虑整合一个 CoreAudio 的轮子dll来解决实际问题!

在这里插入图片描述
在这里插入图片描述
std::StringStream ⇒ std::ios::binary ⇒ std::ofstream
在这里插入图片描述
在这里插入图片描述

Loopback.dll

#ifndef _DLL_CORE_AUDIO_LOOPBACK_LOCK
#define _DLL_CORE_AUDIO_LOOPBACK_LOCK#pragma data_seg("Shared")
HANDLE hMutex = NULL;
UINT   liveIndex = 0;
CComPtr<IMMDeviceEnumerator> pEnumerator;
#pragma data_seg()
#pragma comment(linker, "/section:Shared,rws")
class TimespanGuard {
public:TimespanGuard(){this->_bof_time = GetTickCount();this->_token = "Timespan";}TimespanGuard(std::string token){this->_bof_time = GetTickCount();_token = token;}~TimespanGuard(){this->_eof_time = GetTickCount();std::cout << "" << this->_token << " > " << (this->_eof_time - this->_bof_time) << "ms elapsed" << std::endl;}private:DWORD _bof_time, _eof_time;std::string _token;
};
CORE_AUDIO_LOOPBACK_API BOOL WINAPI init(UINT devNum)
{TimespanGuard timespanGuard("init");HRESULT hr{};CoInitializeGuard coInitializeGuard;if (FAILED(coInitializeGuard.result())) {return (FALSE);    // BOOL FALSE 0x0000}hr = pEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));if (FAILED(hr)) {return (FALSE);    // BOOL FALSE 0x0000}Sleep(10);return (TRUE);         // BOOL TRUE  0x0001
}

在这里插入图片描述

CORE_AUDIO_LOOPBACK_API BOOL WINAPI getChunk(UINT devNum, UINT (*dtChunk)[2], UINT nDimension)
{TimespanGuard timespanGuard("getChunk");HRESULT hr{};CoInitializeGuard coInitializeGuard;if (FAILED(coInitializeGuard.result())) {return (FALSE);    // BOOL FALSE 0x0000}hr = pEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));if (FAILED(hr)) {return (FALSE);    // BOOL FALSE 0x0000}std::cout << "getChunk > " << (nDimension) << "x" << (2) << std::endl;for (int i = 0; i < nDimension; i++) {printf("\t#%.4d ", i);for (int j = 0; j < 2; j++) {printf("%8d ", dtChunk[i][j]);dtChunk[i][j] = dtChunk[i][j] + 100;}printf("\n");}Sleep(10);return (TRUE);         // BOOL TRUE  0x0001
}
CORE_AUDIO_LOOPBACK_API BOOL WINAPI release(UINT devNum)
{TimespanGuard timespanGuard("release");CoUninitialize();return (TRUE);         // BOOL TRUE  0x0001
}

XAudio.py

import ctypesif True:loopback = ctypes.CDLL("loopback.dll")if True:loopback.getAudio.argtypes = [c_int, c_char_p, c_int]loopback.getAudio.restype = c_intdevNum = c_int(0)bytesSize = 256bytesName = (' ' * bytesSize).encode('utf-8')result = loopback.getAudio(devNum, bytesName, bytesSize)print('DLL invoked > ', result, (bytesName.decode('gb2312')))

GetBitmapBits 后位图颠倒

	dumpCache(dataBuff, result);GetBitmapBits(hOutputBitmap, nBytesSize, rawData); // 获取位图的位for (int i = 0; i < nBytesSize; i++) {int row, column = 0;row = (sHeight - (i / bm.bmWidthBytes)) - 1;column = (i % bm.bmWidthBytes);dataBuff[result + row * bm.bmWidthBytes + column] = (rawData[i] & 0x00FF);}result += nBytesSize;
dumpCache(dataBuff, result);

dumpCache

BOOL dumpCache(BYTE* dataBuff, UINT buffSize)
{for (int i = 0; i < buffSize; i++) {printf("%.2X ", dataBuff[i]);if (i % 16 == 15)printf("\n");}printf("\n");return (TRUE);
}

getBitmapHeader

UINT getBitmapHeader(HDC hDC, HBITMAP hBitmap, BYTE* dataBuff, UINT buffSize)
{UINT result = 0;int iBits;//当前显示分辨率下每个像素所占字节数WORD wBitCount;//位图中每个像素所占字节数//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数DWORD dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten;BITMAP Bitmap;//位图属性结构BITMAPFILEHEADER bmfHdr;//位图文件头结构BITMAPINFOHEADER bi;//位图信息头结构LPBITMAPINFOHEADER lpbi;//指向位图信息头结构HANDLE fh, hDib, hPal;HPALETTE hOldPal = NULL;//定义文件,分配内存句柄,调色板句柄//计算位图文件每个像素所占字节数iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);if (iBits <= 1)wBitCount = 1;else if (iBits <= 4)wBitCount = 4;else if (iBits <= 8)wBitCount = 8;else if (iBits <= 24)wBitCount = 24;elsewBitCount = 32;//计算调色板大小if (wBitCount <= 8)dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);//设置位图信息头结构GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);bi.biSize = sizeof(BITMAPINFOHEADER);bi.biWidth = Bitmap.bmWidth;bi.biHeight = Bitmap.bmHeight;bi.biPlanes = 1;bi.biBitCount = wBitCount;bi.biCompression = BI_RGB;bi.biSizeImage = 0;bi.biXPelsPerMeter = 0;bi.biYPelsPerMeter = 0;bi.biClrUsed = 0;bi.biClrImportant = 0;dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;//为位图内容分配内存hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);*lpbi = bi;// 处理调色板  hPal = GetStockObject(DEFAULT_PALETTE);if (hPal){hDC = ::GetDC(NULL);hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);RealizePalette(hDC);}// 获取该调色板下新的像素值GetDIBits(hDC, hBitmap, 0, (UINT)Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize, (BITMAPINFO*)lpbi, DIB_RGB_COLORS);//恢复调色板  if (hOldPal){SelectPalette(hDC, hOldPal, TRUE);RealizePalette(hDC);::ReleaseDC(NULL, hDC);}// 设置位图文件头bmfHdr.bfType = 0x4D42; // "BM"dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;bmfHdr.bfSize = dwDIBSize;bmfHdr.bfReserved1 = 0;bmfHdr.bfReserved2 = 0;bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;// 写入位图文件头memcpy(dataBuff, (BYTE*)&bmfHdr, sizeof(BITMAPFILEHEADER));result += sizeof(BITMAPFILEHEADER);memcpy((dataBuff + result), (BYTE*)lpbi, ((DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize));result += sizeof(BITMAPINFOHEADER);result += dwPaletteSize;//清除  GlobalUnlock(hDib);GlobalFree(hDib);return (result);
}

这篇关于Parade Series - CoreAudio Loopback的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/922800

相关文章

路由器的Loopback地址是什么意思?

本地环回接口(或地址),亦称回送地址(loopback address)。 此类接口是应用最为广泛的一种虚接口,几乎在每台路由器上都会使用。常见于如下用途: 1 作为一台路由器的管理地址  系统管理员完成网络规划之后,为了方便管理,会为每一台路由器创建一个loopback 接口,并在该接口上单独指定一个IP 地址作为管理地址,管理员会使用该地址对路由器远程登录(telnet )

【HDU】2389 Rain on your Parade 二分匹配 Hopcroft-Krap算法

传送门:【HDU】2389 Rain on your Parade 题目分析: 这题目非要我学Hopcroft-Krap= =||。。普通的DFS版的二分匹配不行,最大流又爆内存。。不得不学更好的算法了。 二分匹配的其他性质我也不多说了,不会的自行搜索,网上很多的。 现在我主要对该算法的实现发表一下自己的见解。(算法复杂度的证明不会,论文没看太懂) 该算法的核心思想是通过bfs寻找

【HDU】4927 Series 1 高精度

传送门:【HDU】4927 Series 1 题目分析:公式很好推,到最后就是C(n-1,0)*a[n]-C(n-1,1)*a[n-1]+C(n-1,2)*a[n-2]+...+C(n-1,n-1)*a[n]。 用C(n,k)=C(n,k-1)*(n-k+1)/k即可快速得到一行的二项式系数。 我看JAVA不到1000B 15分钟就能过。。。我又敲了大数模板然后将近2个小时才过T U

【HDU】4928 Series 2 模拟

传送门:【HDU】4928 Series 2 题目分析: 代码如下: #include <cstdio>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )#

PostgreSQL 中的 `generate_series` 函数使用

1. 概述 在 PostgreSQL 中,generate_series 是一个非常实用的内置函数,它能够根据给定的起始值和结束值生成一系列连续的数字。这一功能对于需要生成大量连续数据或进行批量操作的场景非常有用。本文将详细介绍 generate_series 函数的基本用法,并通过一些简单的示例帮助你更好地理解和应用这一函数。 2. 基本用法 generate_series 函数的基本语法

iOS CoreAudio学习笔记(二)—— The Story of Sound

在上一章,我们初次尝试了CoreAudio API:它提供了什么以及怎样调用它的函数。现在是时候往回一步来看看一张更大的图:一开始CoreAudio访问的问题。 这一章将介绍基础的声音科学,它是什么,它怎样工作。事实证明,计算机的数字化天性使它们并不那么适合处理连续的模拟信号。这引导了对信号采样的思想,或者将平滑的声波斩为频率足够大的离散值,而人耳无法注意到差别。这一章覆盖了这些采样在数字化形态

echarts中series中的数据如何如何循环显示数据

echarts中的数据格式如下 var option = { title : { text: '月份对比', subtext: '' }, tooltip : { trigger: 'axis' }, legend: { data:['3月','4月','5月','6月'] }, toolbox: { show : false, feature : { dataView : {show: tru

Pandas-高级处理(六):map()【将自定义函数作用于Series的每个元素】、apply()【将自定义函数作用于DF的行或者列】、applymap()函数【将自定义函数作用于DF的所有元素】

一、map map()是Series对象的一个函数,DataFrame中没有map(),map()的功能是将一个自定义函数作用于Series对象的每个元素。 现在使用map()函数来将data1这一列的数据改为保留三位小数显示 df['data1'] = df['data1'].map(lambda x : "%.3f"%x) 二、apply apply()函数的功能是将一个自定

论文笔记:Estimating future human trajectories from sparse time series data

sigspatial 2023 humob竞赛paper hiimryo816/humob2023-MOBB (github.com) 1 数据集分析 这里只分享了HuMob数据集1的内容 1.1 假日分析 对HuMob数据集#1地理数据的方差分析显示了非工作日的模式 在某些天的y坐标方差中有显著的峰值,这是非工作日的象征【x坐标有相似的模式】 ——>识别了任务1数据集中最有可能是

Cisco 2500 Series Access Server User Guide开头

读到Preparing to Install the Cisco 2500 Series Access Server 2-3