首页 文章 精选 留言 我的

精选列表

搜索[chrome扩展],共10000篇文章
优秀的个人博客,低调大师

Golang 基于chrome浏览器语音识别web演示系统WebHTK开发之 引擎篇

要说引擎篇,也谈不上。底层语音识别的实现,是基于HTK开源语音识别工具:http://htk.eng.cam.ac.uk/#前面用过这个工具,也用JNI转成java可调用的接口,所以还算比较熟悉。这次引擎,也只是用cgo来转。HMM模型都是用HTK的工具训练好的,只要有数据,baidu,google上教程还是很多的,自带的HTKBOOK就是最权威的教程。 在实现阶段,主要就是用到三个工具:HCopy(提取特征),HVite(viterbi算法识别),HParse(制作语法词网)。看看都需要哪些文件: 这些文件中,只有上述三个HCopy.c,HVite.c,HParse.c还有main主函数,所以只要把三个main函数重命名下,传参仍不变,并修改下这三个文件中一些相同命名的函数(比方Usage这类的),再写个asr.h的头文件,把上述重命名的三个main函数加进去就ok了,asr.h: 1 2 3 4 5 #ifndef ASR_H int HCopy( int argc, char *argv[]); int HVite( int argc, char *argv[]); int HParse( int argc, char *argv[]); #endif 再看下HTKengine.go: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package HTKengine //#include "asr.h" //#include "string.h" //#include "stdlib.h" import "C" import "unsafe" type cmd struct { HCOPY string HVITE string HPARSE string } var Command *cmd = &cmd{ "HCopy" , "HVite" , "HParse" } func HCopy(args []string) { arg := make([](*_Ctype_char), 0 ) l := len(args) for i, _ := range args { char := C.CString(args[i]) defer C.free(unsafe.Pointer( char )) strptr := (*_Ctype_char)(unsafe.Pointer( char )) arg = append(arg, strptr) } C.HCopy(C. int (l), (**_Ctype_char)(unsafe.Pointer(&arg[ 0 ]))) } func HVite(args []string) { arg := make([](*_Ctype_char), 0 ) l := len(args) for i, _ := range args { char := C.CString(args[i]) defer C.free(unsafe.Pointer( char )) strptr := (*_Ctype_char)(unsafe.Pointer( char )) arg = append(arg, strptr) } C.HVite(C. int (l), (**_Ctype_char)(unsafe.Pointer(&arg[ 0 ]))) } func HParse(args []string) { arg := make([](*_Ctype_char), 0 ) l := len(args) for i, _ := range args { char := C.CString(args[i]) defer C.free(unsafe.Pointer( char )) strptr := (*_Ctype_char)(unsafe.Pointer( char )) arg = append(arg, strptr) } C.HParse(C. int (l), (**_Ctype_char)(unsafe.Pointer(&arg[ 0 ]))) } 原来的main都是要跟上args参数的,这里把他作为接口调用,所以还是需要传进args []string。在我前面的博客中,有提到cgo,可以参考下: golang在window环境下用cgo编译c语言 Golang cgo编程 [] string 转 C语言 char** 在前面录音篇,有大概讲到在服务器保存wav文件,HCopy就直接跟在wav保存的代码后,而HVite跟在HCopy后。现在时间不允许,否则,可以改下HCopy的代码,直接传byte[]数据。其实在pocketsphinx中就是这么实现的,有空也可以给pocketsphinx写几个cgo的接口来调用。 关于这个系列的博客,应该不会再写什么了,web到这,功能已经完成80%,后面也就是添加些,动态添加待识别语句到数据库的功能,说白了,就是你想识别哪些语句,你可以自己定义,提交给服务器,通过HParse重新制作词网来搞定的。也没有什么跟web开发有很大关系的,顶多是涉及到数据库,不过目前我对数据库了解不多,也只用到简单的CRUD操作,所以嘛,就不多写了。 上周接到网易游戏的面试电话,木有任何准备,被虐的狗一样啊。所以近阶段的博客,应该会写些java,golang数据结构方面的吧。 本文转自 ponpon_ 51CTO博客,原文链接:http://blog.51cto.com/liuxp0827/1374334,如需转载请自行联系原作者

优秀的个人博客,低调大师

Golang 基于chrome浏览器语音识别web演示系统WebHTK开发之 UI篇

没啥好说的,直接上现阶段的HTML代码,后续修改,再更新该篇博客。 record.html: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 <!DOCTYPE html> <html> <head> <meta charset= "utf-8" /> <meta http-equiv= "X-UA-Compatible" content= "IE=edge" /> <meta name= "viewport" content= "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name= "keywords" content= "PONPON,HTK,Go语言" /> <meta name= "description" content= "基于Beego开发语音识别演示系统" /> <meta name= "generator" content= "PONPON" /> <link href= "/static/css/bootstrap.min.css" rel= "stylesheet" > <link href= "/static/css/docs.css" rel= "stylesheet" > <link href= "http://cdn.bootcss.com/highlight.js/7.3/styles/github.min.css" rel= "stylesheet" > <link rel= "shortcut icon" href= "/static/img/Logoicon.jpg" > <link rel= "stylesheet" href= "http://libs.baidu.com/fontawesome/4.0.3/css/font-awesome.min.css" /> <link rel= "alternate" type= "application/rss+xml" href= "/rss.xml" /> <script type= "text/javascript" src= "/static/lib/recorder.js" > </script> <script type= "text/javascript" src= "/static/lib/jquery-1.10.1.min.js" > </script> <script type= "text/javascript" src= "/static/lib/recController.js" > </script> <title>WebHTK 演示系统</title> </head> <body> <nav id= "header" > <div class= "container960 text-center" > <h3 id= "header-h" class= "center" >闽南语 - 语音识别演示系统</h3> <ul id= "resultbox" class= "center" style= "padding-top:425px;font-size:20px;text-align: center;color:#FFC8B6;font-family:'微软雅黑'" > <li >识别结果</li> </ul> <form style= "padding-top:20px;" > <a id= "img" href= "javascript://" > <img src= "/static/img/aa.png" style= "width:85px;height:85px;" alt= "" /> </a> </form> <div id= "message" style= "padding-top:10px;font-size:16px;color:#F5FFFA;text-align: center;font-family:'微软雅黑'" >点击麦克风,开始录音!</div> <script type= "text/javascript" > var recording = false ; function test() { if (!recording) { document.getElementById( "img" ).innerHTML= "<img src='/static/img/a1.png' style='width:85px;height:85px;'' alt=''/>" ; toRecord(); recording= true ; } else { document.getElementById( "img" ).innerHTML= "<img src='/static/img/aa.png' style='width:85px;height:85px;'' alt=''/>" ; toSend(); recording = false ; } }; function toRecord(){ rec.record(); var dd = ws.send( "start" ); $( "#message" ).text( "再次点击,结束录音!" ); intervalKey = setInterval( function () { rec.exportWAV( function (blob) { rec.clear(); ws.send(blob); }); }, 300); } function toSend(){ rec.stop(); if (intervalKey == null ) { $( "#message" ).text( "请先录音再发送!" ); return }; ws.send(sampleRate); ws.send(channels); ws.send( "stop" ); rec.clear(); clearInterval(intervalKey); intervalKey = null ; } </script> </div> </nav> <audio class= "hide" controls autoplay></audio> </body> </html> recorder.js: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 ( function (window) { var WORKER_PATH = '/static/lib/recorderWorker.js' ; var Recorder = function (source, chan, cfg) { var config = cfg || {}; var channels = chan || 1; var bufferLen = config.bufferLen || 8192; this .context = source.context; this .node = this .context.createJavaScriptNode(bufferLen, channels, channels); var worker = new Worker(config.workerPath || WORKER_PATH); worker.postMessage({ command: 'init' , config: { sampleRate: this .context.sampleRate } }); var recording = false , currCallback; this .node.onaudioprocess = function (e) { if (!recording) return ; worker.postMessage({ command: 'record' , buffer: [ e.inputBuffer.getChannelData(0) ] }); } this .configure = function (cfg) { for ( var prop in cfg) { if (cfg.hasOwnProperty(prop)) { config[prop] = cfg[prop]; } } } this .record = function () { recording = true ; } this .stop = function () { recording = false ; } this .clear = function () { worker.postMessage({ command: 'clear' }); } this .getBuffer = function (cb) { currCallback = cb || config.callback; worker.postMessage({ command: 'getBuffer' }) } this .exportWAV = function (cb, type) { currCallback = cb || config.callback; type = type || config.type || 'audio/wav' ; if (!currCallback) throw new Error( 'Callback not set' ); worker.postMessage({ command: 'exportWAV' , type: type }); } worker.onmessage = function (e) { var blob = e.data; currCallback(blob); } source.connect( this .node); this .node.connect( this .context.destination); }; window.Recorder = Recorder; })(window); recorderWorker.js: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 var recLength = 0, recBuffersL = [], sampleRate; this .onmessage = function (e) { switch (e.data.command) { case 'init' : init(e.data.config); break ; case 'record' : record(e.data.buffer); break ; case 'exportWAV' : exportWAV(e.data.type); break ; case 'getBuffer' : getBuffer(); break ; case 'clear' : clear(); break ; } }; function init(config) { sampleRate = config.sampleRate; } function record(inputBuffer) { recBuffersL.push(inputBuffer[0]); recLength += inputBuffer[0].length; } function exportWAV(type) { var bufferL = mergeBuffers(recBuffersL, recLength); var interleaved = interleave(bufferL); var dataview = encodeWAV(interleaved); var audioBlob = new Blob([dataview], { type: type }); this .postMessage(audioBlob); } function getBuffer() { var buffers = []; buffers.push(mergeBuffers(recBuffersL, recLength)); this .postMessage(buffers); } function clear(inputBuffer) { recLength = 0; recBuffersL = []; } function mergeBuffers(recBuffers, recLength) { var result = new Float32Array(recLength); var offset = 0; for ( var i = 0; i < recBuffers.length; i++) { result.set(recBuffers[i], offset); offset += recBuffers[i].length; } return result; } function interleave(inputL) { var length; var result; var index = 0, inputIndex = 0; if (sampleRate == 48000) { length = inputL.length / 6; result = new Float32Array(length); while (index < length) { result[index++] = (inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++]) / 6; } } else if (sampleRate == 44100) { length = inputL.length / 6; result = new Float32Array(length); while (index < length) { if (inputIndex % 12 == 0) { result[index++] = (inputL[inputIndex] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++]) / 7; } else { result[index++] = (inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++]) / 6; }; } } else { length = inputL.length; result = new Float32Array(length); while (index < length) { result[index++] = inputL[inputIndex++]; } }; return result; } function floatTo16BitPCM(output, offset, input) { for ( var i = 0; i < input.length; i++, offset += 2) { var s = Math.max(-1, Math.min(1, input[i])); output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true ); } } function writeString(view, offset, string) { for ( var i = 0; i < string.length; i++) { view.setUint8(offset + i, string.charCodeAt(i)); } } function encodeWAV(samples) { var buffer = new ArrayBuffer(samples.length * 2); var view = new DataView(buffer); floatTo16BitPCM(view, 0, samples); return view; } recController.js: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 var onFail = function (e) { console.log( 'Rejected!' , e); }; var onSuccess = function (s) { var context = new webkitAudioContext(); var mediaStreamSource = context.createMediaStreamSource(s); rec = new Recorder(mediaStreamSource, channels); sampleRate = 8000; } navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; var rec; var intervalKey = null ; var audio = document.querySelector( '#audio' ); var sampleRate; var channels = 1; function startRecording() { if (navigator.getUserMedia) { navigator.getUserMedia({ audio: true }, onSuccess, onFail); } else { console.log( 'navigator.getUserMedia not present' ); } } startRecording(); //-------------------- var ws = new WebSocket( 'ws://' + window.location.host + '/join' ); ws.onopen = function () { console.log( "Openened connection to websocket" ); }; ws.onclose = function () { console.log( "Close connection to websocket" ); } ws.onerror = function () { console.log( "Cannot connection to websocket" ); } ws.onmessage = function (result) { var data = JSON.parse(result.data); console.log( '识别结果:' + data.Pinyin); var result = document.getElementById( "resultbox" ) result.getElementsByTagName( "li" )[0].innerHTML = data.Hanzi; document.getElementById( "message" ).innerHTML = "点击麦克风,开始录音!" ; } 进入页面: 正在录音: 识别结果,目前还为将拼音转换为汉字,下图为“点亮星光”的显示结果图: 本文转自 ponpon_ 51CTO博客,原文链接:http://blog.51cto.com/liuxp0827/1367846,如需转载请自行联系原作者

优秀的个人博客,低调大师

微软开源 mimalloc,面向现代的高性能、可扩展内存分配器

内存分配器是系统软件中最基础也最容易被忽视的组件之一。微软研究院的 Daan Leijen 为此付出了多年心血,mimalloc 正是他给出的答案。这个项目不仅仅是代码,更是一种关于"什么是好的内存分配器"的设计哲学的体现。 mimalloc 的核心设计围绕着一个简单但深刻的观察:传统的内存分配器往往是全局的,所有线程竞争同一批内存资源,这会成为性能瓶颈。mimalloc 的解决方案是让每个线程拥有自己独立的堆——thread-local heaps。这样分配和释放大多数时候只需要访问本地数据结构,完全避免了锁竞争。这个设计被称为"per-thread local heaps",是 mimalloc 高性能的关键之一。 从代码规模看,mimalloc 约 12K 行 C 代码,这个规模对于一个生产级别的内存分配器来说相当克制。Daan Leijen 在设计中特别强调了"clear data structures"——清晰的数据结构。这不仅有利于代码维护,也使得内存布局更加可预测,有助于减少碎片化。在内存碎片化这个老问题上,mimalloc 通过 free list sharding 和 page stealing 等机制来缓解。前者将不同大小的内存块分开管理,后者允许线程在需要时从其他线程的本地堆中"偷"内存页面,实现高效的跨线程内存共享。 实际应用是最好的背书。NoGIL CPython 3.13+ 采用了 mimalloc 作为默认分配器,这对 Python 的性能提升有显著帮助。Unreal Engine 和《死亡搁浅》游戏同样在使用 mimalloc。GitHub 上超过 12K stars 的成绩也证明了社区对它的认可。 mimalloc 另一个值得关注的设计目标是提供"bounded worst-case allocation times"。对于实时系统或者需要确定性的场景来说,这一点比平均性能更重要。传统的内存分配器在极端情况下可能出现较长的分配延迟,而 mimalloc 通过其数据结构设计将最坏情况控制在可预测范围内。 作为一种 drop-in replacement for malloc/free,mimalloc 的集成成本很低。不需要修改现有代码,只需要链接新的分配器即可。这对于想要尝试新技术但又不想大规模重构的项目来说是个好消息。 来源:Microsoft Research (https://www.microsoft.com/en-us/research/blog/mimalloc-a-high-performance-scalable-memory-allocator-for-the-modern-era/)

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册