api 静态回调

未解决  未打赏  
max max  悬赏: 5 金币
发布:2018-12-18 23:04:15 分类:问答
无法录音,(本机自带录音机能正常录音)

问题:
调用 waveInOpen 能响应 WIM_OPEN 消息,打开录音设备
调用 waveInStart 收不到 WIM_DATA 消息,运行几秒后直接闪退

图片名称

record 库源码:
//record 录音
namespace record{

/* ****************API函数声明区***************** */
::Winmm := ..raw.loadDll("Winmm.dll");
var waveInOpenA = Winmm.api("waveInOpen","INT(pointer& phwi,INT uDeviceID,struct pwfx,POINTER dwCallback,INT dwCallbackInstance,INT fdwOpen)");
var waveInGetIDA = Winmm.api("waveInGetID","INT(pointer hwi,pointer& lpuDeviceID)")
var waveInGetDevCapsA = Winmm.api("waveInGetDevCapsA","INT(INT uDeviceID,struct& pwic,INT cbwic)");
var waveInGetErrorTextA = Winmm.api("waveInGetErrorTextA","INT(INT mmrError,string &pszText,INT cchText)")
//var waveInPrepareHeader = Winmm.api("waveInPrepareHeader","INT(pointer hwi, struct& pwh,INT cbwh);");
//var waveInUnprepareHeader = Winmm.api("waveInUnprepareHeader","INT(pointer hwi, struct& pwh,INT cbwh);");
//var waveInAddBuffer = Winmm.api("waveInAddBuffer","INT(pointer hwi, struct& pwh,INT cbwh);");


/* ****************结构体定义区***************** */
class WAVEINCAPS{
WORD wMid; //驱动程序标识
WORD wPid; //产品标识
INT vDriverVersion;//驱动程序版本号
BYTE szPname[32];//制造商名称
INT dwFormats; //支持格式
WORD wChannels; //声道
WORD wReserved1; //保留参数
}

//缓存结构
class LPWAVEHDR {
pointer lpData; //指向波形数据缓冲区
INT dwBufferLength;//波形数据缓冲区的长度
INT dwBytesRecorded;//若首部用于输入, 指出缓冲区中的数据量
INT dwUser;//指定用户的32位数据
INT dwFlags;//缓冲区标志
INT dwLoops;//循环播放次数, 仅用于输出缓冲区
pointer lpNext;//保留
INT reserved; //保留
};

//采集音频的格式,结构体
class WAVEFORMATEX{
WORD wFormatTag; //声音格式为PCM
WORD nChannels; //采样声道数,1声道
INT nSamplesPerSec; //采样率,22050次/秒
INT nAvgBytesPerSec; //每秒的数据率,就是每秒能采集多少字节的数据,字节数=声道数*取样率*比特率/8
WORD nBlockAlign; //指定块对齐(每个样本的字节数), 块对齐是数据的最小单位=声道数*比特率/8
WORD wBitsPerSample; //采样位数.wFormatTag为WAVE_FORMAT_PCM时,为8或者16,采样大小(字节), 每个样本的量化位数
WORD cbSize;//wFormatTag为WAVE_FORMAT_PCM时,忽略此参数
}


/* ****************函数声明区***************** */


//返回系统中就绪的波形声音输入设备的数量
waveInGetNumDevs = function(){
return Winmm.waveInGetNumDevs();
}

//检查指定波形输入设备的特性
waveInGetDevCaps = function(uDeviceID){
return waveInGetDevCapsA(uDeviceID,WAVEINCAPS(),..raw.sizeof(WAVEINCAPS()));
}

//加入到准备的录音缓冲区中
waveInPrepareHeader = function(hWaveIn,pwh,cbwh){
..console.log("准备缓冲区...")
return Winmm.waveInPrepareHeader(hWaveIn,pwh,cbwh);
}

waveInUnprepareHeader = function(hWaveIn,pwh,cbwh){
..console.log("清空缓冲区...")
return Winmm.waveInUnprepareHeader(hWaveIn,pwh,cbwh);
}

//将缓冲区发送给设备,若缓冲区填满,则不起作用。
waveInAddBuffer = function(hWaveIn,pwh,cbwh){
..console.log("将缓冲区加入音频输入设备...")
return Winmm.waveInAddBuffer(hWaveIn,pwh,cbwh);
}

//检索由给定错误号标识的错误的文本描述。
waveInGetErrorText = function(mmrError){
//INT mmrError, 代码编号
//ustring pszText, 缓冲区
//INT cchText, 缓冲区大小 文本的长度一般不超过 MAXERRORLENGTH = 128; 如果缓冲区太小, 文本会被截断
var pszText = ..raw.buffer(128);
return waveInGetErrorTextA(mmrError,pszText,128);
}

//函数获取给定波形音频输入设备的设备标识符。
waveInGetID = function(hWaveIn,lpuDeviceID){
//hWaveIn, 待获取输入设备的句柄
//lpuDeviceID, 用于接收声音设备ID
return waveInGetIDA(hWaveIn,lpuDeviceID);
}

//打开指定的音频输入设备,进行录音
waveInOpen = function(uDeviceID,nChannels,nSamplesPerSec,wBitsPerSample){
waveFormat = WAVEFORMATEX();
waveFormat.wFormatTag = 0x1/*_WAVE_FORMAT_PCM*/;
waveFormat.nChannels = nChannels;//声道数
waveFormat.nSamplesPerSec = nSamplesPerSec;//取样率
waveFormat.wBitsPerSample = wBitsPerSample;//比特率
waveFormat.nAvgBytesPerSec = nChannels * nSamplesPerSec * wBitsPerSample / 8;//传输速率
waveFormat.nBlockAlign = nChannels * wBitsPerSample / 8;//块对齐

fun_c = ..raw.tostdcall(
function(hWaveIn,uMsg,dwInstance,dwParam1,dwParam2){
select(uMsg) {
case 958/*WIM_OPEN*/ {
..console.log("WIM_OPEN","3.>音频设备已经打开...")
}
case 960/*WIM_DATA*/ {
Param = ..raw.convert(dwParam1,LPWAVEHDRS)
..console.log(..string.format("WIM_DATA","4.>n缓冲区%d存满...",Param.dwUser ))
//waveInAddBuffer(hWaveIn,Param,32);
}
case 959/*WIM_CLOSE*/ {
..console.log("WIM_CLOSE","5.>关闭音频设备...")
waveInStop(hWaveIn);
waveInReset(hWaveIn);
}
else {
..console.log("未定义信息")
}
}
},"void(pointer hWaveIn,INT uMsg,INT dwInstance,pointer dwParam1,pointer dwParam2)"
);
return waveInOpenA(,uDeviceID,waveFormat,fun_c,0,0x30000/*_CALLBACK_FUNCTION*/);
/* 返回结果
MMSYSERR_BADDEVICEID = 2; {设备ID超界}
MMSYSERR_ALLOCATED = 4; {指定的资源已被分配}
MMSYSERR_INVALHANDLE = 5; {设备句柄无效}
MMSYSERR_NODRIVER = 6; {没有安装驱动程序}
MMSYSERR_NOMEM = 7; {不能分配或锁定内存}
MMSYSERR_HANDLEBUSY = 12; {其他线程正在使用该设备}
WAVERR_BADFORMAT = 32; {设备不支持请求的波形格式}
*/
}

//开始录音
waveInStart = function(hWaveIn){
..console.log("[操作]开始录音...")
return Winmm.waveInStart(hWaveIn);
}

//暂停录音
waveInStop = function(hWaveIn){
..console.log("[操作]录音停止...")
return Winmm.waveInStop(hWaveIn);
}

//终止输入, 位置清0; 放弃未处理的缓冲区并返回给程序
waveInReset = function(hWaveIn){
..console.log("[操作]录音重置...")
return Winmm.waveInReset(hWaveIn);
}

//停止声音输入 提示: 如果未启动则调用无效, 但也返回 0; 缓冲区会被返回, TWaveHdr 结构中的 dwBytesRecorded 将包含返回的实际数据的长度.
waveInClose = function(hWaveIn){
..console.log("[操作]关闭录音...")
return Winmm.waveInClose(hWaveIn);
}
}


/**intellisense()
_MMSYSERR_NOERROR=@0/*MMSYSERR_NOERROR*/
_MMSYSERR_ERROR=@1/*MMSYSERR_ERROR*/
_MMSYSERR_BADDEVICEID=@2/*MMSYSERR_BADDEVICEID*/
_MMSYSERR_NOTENABLED=@3/*MMSYSERR_NOTENABLED*/
_MMSYSERR_ALLOCATED=@4/*MMSYSERR_ALLOCATED*/
_MMSYSERR_INVALHANDLE=@5/*MMSYSERR_INVALHANDLE*/
_MMSYSERR_NODRIVER=@6/*MMSYSERR_NODRIVER*/
_MMSYSERR_NOMEM=@7/*MMSYSERR_NOMEM*/
_MMSYSERR_NOTSUPPORTED=@8/*MMSYSERR_NOTSUPPORTED*/
_MMSYSERR_BADERRNUM=@9/*MMSYSERR_BADERRNUM*/
_MMSYSERR_INVALFLAG=@10/*MMSYSERR_INVALFLAG*/
_MMSYSERR_INVALPARAM=@11/*MMSYSERR_INVALPARAM*/
_MMSYSERR_HANDLEBUSY=@12/*MMSYSERR_HANDLEBUSY*/
_MMSYSERR_INVALIDALIAS=@13/*MMSYSERR_INVALIDALIAS*/
_MMSYSERR_BADDB=@14/*MMSYSERR_BADDB*/
_MMSYSERR_KEYNOTFOUND=@15/*MMSYSERR_KEYNOTFOUND*/
_MMSYSERR_READERROR=@16/*MMSYSERR_READERROR*/
_MMSYSERR_WRITEERROR=@17/*MMSYSERR_WRITEERROR*/
_MMSYSERR_DELETEERROR=@18/*MMSYSERR_DELETEERROR*/
_MMSYSERR_VALNOTFOUND=@19/*MMSYSERR_VALNOTFOUND*/
_MMSYSERR_NODRIVERCB=@20/*MMSYSERR_NODRIVERCB*/
_MMSYSERR_LASTERROR=@20/*MMSYSERR_LASTERROR*/
_WAVERR_BADFORMAT=@32/*WAVERR_BADFORMAT*/
_WAVERR_STILLPLAYING=@33/*WAVERR_STILLPLAYING*/
_WAVERR_UNPREPARED=@34/*WAVERR_UNPREPARED*/
end intellisense**/

调用代码:
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=511;bottom=139)
winform.add(
init={cls="button";text="设备检测";left=47;top=54;right=118;bottom=93;z=2};
start={cls="button";text="开始录音";left=216;top=52;right=292;bottom=91;z=1};
stop={cls="button";text="结束录音";left=377;top=54;right=467;bottom=95;z=3}
)
/*}}*/

import record;
import console;

var mmresult,hwi;//返回结果

getErrInfo = function(mmresult){
if(mmresult){
var result,err = record.waveInGetErrorText(mmresult);
console.log(err);
return err;
}
return ;
}

winform.init.oncommand = function(id,event){
console.log(string.format("1.>检测到共有 %d 录音设备",record.waveInGetNumDevs()));
var result,info = record.waveInGetDevCaps(0);
if(result == 0){
console.log("2.>获取第1个设备成功,设备信息:",string.fromUnicodeIf(info.szPname));
}
}

winform.start.oncommand = function(id,event){
mmresult,hwi = record.waveInOpen(0,1,22050,8);//打开录音设备
if(mmresult == 0){
var pwhList = {};
var bufsize = 6400;

//录音前双缓冲初始化
for(i=1;2;1){

pwhList[i] = record.LPWAVEHDR();
pwhList[i].lpData = raw.toPointer(raw.buffer(bufsize));
pwhList[i].dwBufferLength = bufsize;
pwhList[i].dwLoops = 1;

getErrInfo(record.waveInPrepareHeader(hwi,pwhList[i],32));
getErrInfo(record.waveInAddBuffer(hwi,pwhList[i],32));
sleep(5)
}
getErrInfo(record.waveInStart(hwi))//开始录音

}else {
var result,err = record.waveInGetErrorText(mmresult);
console.log("打开设备错误:",err)
}
}

winform.stop.oncommand = function(id,event){
if(mmresult == 0){

var tag = true;
var statList = {}
var sum = 0;

//清空缓存并结束录音
while(tag){
for(i=1;#pwhList;1){
statList[i] = record.waveInUnprepareHeader(hwi,pwhList[i],32)
sum+=statList[i]
}

if(sum){
console.log("缓冲区还在队列中")
}else {
console.log("清除缓存成功")
tag = false;
getErrInfo(record.waveInClose(hwi))
}
sum = 0;
sleep(5);
}
}
}

winform.show();
win.loopMessage();
return winform;

[ 发单/接单 ]
换IP投票软件
PC蛋蛋自动挂机投注
新浪微博发微博显示尾巴的方法,比如显示来自iphone 7
百度文库批量自动上传软件
一点资讯app刷阅读量/评论/收藏/订阅功能/手机号注册
定做一个阿迪达斯官网注册器(需要破点击文字式验证码)
定制人人网自动注册/修改资料/采集/私聊软件
酷狗繁星直播网页协yi
YY多功能刷订阅刷粉丝
滑块验证码本地识别
狼人杀POST QQ登录注册 获取金币数量
做个贴吧发发帖的软件懂的来
今日头条账号保存cookie
抖音粉丝软件定做,只要粉丝
百家号自媒体发文软件定制
哔哩哔哩播放量
读取TB某个商品上架时间和相关信息
网易博客软件定制
定制天涯论坛发帖软件
定制今日头条批量自动发私信软件
[ 站内搜索 ]
[ 最近热帖 ]
万能助手 -- 扩展库大全集 13752
用aardio创建web工程图文讲解(1) 12840
电脑编程入门自学:Fiddler https 抓包时提示创建根证书不成功问题彻底解决(https插件dll方式) 11743
aardio绘图演示 11413
通过chrome.dll中间件控制外部chrome浏览器 10125
我常用的aardio技巧 9773
《边学C语言边赚钱——简码编程入门教程》系列集合 9616
aardio使用http或whttp进行get/post请求时经常cookies失效怎么办?__电脑计算机编程入门教程自学 9322
[源码下载]简码视频加密解密播放工具个人版v1.0发布,永久免费开源的知识变现神器 8557
python人工智能爬虫系列:怎么查看python版本_电脑计算机编程入门教程自学 8048
编程入门教程:aardio批量上传文件并显示进度条 7883
aardio调用nodejs的ws模块做一个简单的聊天通信示例 7037
电脑计算机编程入门教程自学:原生JavaScript判断字符是否为A-Za-z英文字母 6908
电脑计算机编程入门教程自学:腾讯tx或极验geetest滑块按住拖动完成拼图验证成功破解思路及源码 6501
乐玩插件AARDIO调用 6086
[ 近期热答 ]
电脑计算机编程入门教程自学:什么是buffer缓冲区? 1
aardio_代码编辑框书签管理器开源 1
aardio_怎么用ide库从代码编辑框中取出指定行的源码? 1
aardio_codepage代码页编码乱码暴力猜解工具 1
aardio内嵌echarts图表添加鼠标事件响应功能 2
aardio列表框listbox_模糊查找和精确查找 1
8亿QQ绑定手机泄露:通过腾讯QQ号查询QQ绑定的手机号码漏洞! 1
carl listviewex调用例子----------源码搬运工 2
Aardio内嵌Electron浏览框怎么正确添加启动参数? 1
Aardio取汉字的字节数或字符数 1
怎么实现mssql图片数据的读写 2
aardio_从49个数字里选六个和值为150的不重复的数字 1
在嵌入wps的时候,多了一个 透明的边框,这个怎么消除它 1
万能助手入门帮助教程:学会科学地管理工作文件 1
Aaardio开发内嵌Electron浏览框放服务器上无法下载组件的解决办法 1