整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML、CSS 和 JavaScript等前端開發技術,必備入門級學習書單

          到前端技術,我們通常都會說到"三大塊":HTML、CSS、JavaScript,前端最核心的三項技術。

          從邏輯上講,一個網頁可以視為由這三項技術實現的三層架構有機結合體。


          · 結構層:表述一個頁面中有哪些信息,以及信息之間的關系,由HTML實現。

          · 表現層:決定了頁面中的信息會以怎樣的外觀呈現出來,由CSS實現。

          · 行為層:控制了頁面如何與用戶進行交互,由JS實現。


          除了基本的"三大塊"之外,作為前端開發工程師,還需要掌握以下知識點:

          · HTTP相關:由于前端資源都是瀏覽器通過網絡下載的,所以有必要了解相關的網絡協議。

          · 前端性能優化:讓網頁更快,減少用戶的等待,是前端工程師面臨的重要課題,需要掌握前端性能優化相關的工具和方法。

          · 前端框架:Web業務日趨復雜,對前端開發提出更高要求。學會使用框架開發,很好地解決了jQuery 稱霸時代開發周期太長,復用性低等問題,大大提升了效率。

          · Node相關:在Node.js之前,沒有任何一種腳本語言能貫穿前后端平臺——Node.js可以用JS寫后臺,這對于熟悉JS的前端人員而言會更容易掌握,并且用Node.js可以快速搭建本地服務器。這是很多前端開發者青睞這項技術的原因。

          以下,人郵君就圍繞前端開發所需技能列出一份薦書清單,并按照豆瓣評分和讀者評價給出了推薦指數,請簽收!


          超文本標記語言(Hyper Text Markup Language,HTML),用于描述超文本中內容的顯示方式,如文字以什么顏色、大小來顯示等。HTML從1.0到5.0經歷了巨大的變化,已經成為了一種非常成熟的標記語言。

          入門

          《HTML5權威指南》

          推薦指數:☆☆☆☆


          作者:[美]Adam Freeman 譯者:謝廷晟 牛化成 劉美英

          本書是系統學習網頁設計的參考圖書,全書分為五部分:

          · 介紹學習需要的預備知識和HTML、CSS和JavaScript的進展;

          · 討論HTML元素,并詳細說明了HTML5中新增和修改的元素;

          · 闡述CSS,涵蓋了所有控制內容樣式的CSS選擇器和屬性,并輔以大量代碼示例和圖示;

          · 介紹DOM,剖析如何用JavaScript操縱HTML內容;

          · 講解Ajax、多媒體和canvas元素等HTML5特性。

          本書面向初學者和中等水平Web開發人員,是牢固掌握HTML5、CSS3和JavaScript的必讀之作。


          進階

          《HTML5程序設計(第2版)》

          推薦指數:☆☆☆


          作者:[荷]Peter Lubbers [美]Brian Albers [美]Frank Salim 譯者:柳靖 李杰 劉淼

          本書主要內容包括:

          · HTML5歷史背景、新的語義標簽及與以往HTML版本相比的根本變化;

          · HTML5設計原理;

          · SVG和拖放API相關內容;

          · 逐一討論HTML5的Canvas、Geolocation、Communication、WebSocket、Forms、WebWorkers、Storage等API的使用;

          · 探索了離線Web應用并展望了HTML5未來的發展前景。

          本書面向有一定經驗的Web應用開發人員,對HTML5及未來Web應用技術發展有濃厚興趣的讀者也可以學習參考。


          級聯樣式表(Cascading Style Sheet)簡稱"CSS",通常又稱為"風格樣式表(Style Sheet)",是用來控制網頁外觀的一門技術。各種物聯網設備,不論屏幕尺寸大小,只要有瀏覽器就要用到CSS。

          入門

          《HTML5與CSS3基礎教程(第8版)》

          推薦指數:☆☆☆☆


          作者:[美]Elizabeth Castro [美]Bruce Hyslop 譯者:望以文

          本書是講解HTML和CSS入門知識的經典暢銷書,全面系統地闡述了HTML5和CSS3基礎知識以及實際運用技術,通過大量實例深入淺出地分析了網頁制作的方方面面。主要內容有:

          · 介紹文本、圖像、鏈接、列表、表格、表單等網頁元素;

          · 介紹如何為網頁設計布局、添加動態效果等;

          · 調試和發布;

          · 書中的完整代碼示例,以及更多實例及進階參考資料(配套網站)。

          通過學習本書,零起點讀者即可創建網站,而中水平的開發人員也可以快速了解HTML5新元素、CSS3的奇幻效果、響應式Web設計以及各種最佳實踐。


          進階

          《CSS揭秘》

          推薦指數:☆☆☆☆☆


          作者:[希]LEA VEROU 譯者:CSS魔法

          · 本書是一本注重實踐的教程,作者為我們揭示了47個鮮為人知的CSS技巧;

          · 主要內容包括背景與邊框、形狀、視覺效果、字體排印、用戶體驗、結構與布局、過渡與動畫等;

          · 本書將帶領讀者循序漸進地探尋更優雅的解決方案,攻克每天都會遇到的各種網頁樣式難題。

          《CSS揭秘》是前端工程師、網頁開發人員的進階必備書籍。


          《CSS世界》

          推薦指數:☆☆☆☆


          作者:張鑫旭

          本書主要內容包括:

          · 結構、內容、美化裝飾等方面大量的CSS知識點;

          · 通過大量的實戰案例,詳盡解析CSS的相關知識與常見問題;

          · 專門的配套網站進行實例展示、問題答疑。

          作為一本CSS深入學習的書,書中介紹大量許多前端開發人員都不知道的CSS知識點。通過閱讀本書,讀者會對CSS世界的深度和廣度有一個全新的認識。


          《CSS權威指南(第四版)(上下冊)》

          推薦指數:☆☆☆☆


          作者:[美]Eric A. Meyer [美]Estelle Weyl 譯者:安道

          · 本書全面闡述了 CSS 的實現方式,深入分析了最新的 CSS 規范;

          · 展示了如何通過布局、過渡和動畫、邊框、背景、文本屬性,以及許多其他工具和技術來改善用戶體驗、加快開發速度、避免潛在的錯誤;

          · 如果你是網頁設計師或應用開發者,對復雜的頁面樣式、改進可訪問性以及節省時間和精力感興趣,那你決不能錯過這本書。


          JavaScript是一種解釋型的、基于對象的腳本語言,它能夠將網頁中的文本、圖形、聲音和動畫等各種媒體形式捆綁在一起,形成一個緊密結合的信息源。無論是桌面開發,還是移動應用,JavaScript都是必須掌握的技術。

          入門

          《JavaScript高級程序設計(第3版)》

          推薦指數:☆☆☆☆☆


          作者:[美]Nicholas C.Zakas 譯者:李松峰 曹力

          本書承繼了之前版本全面深入、貼近實戰的特點,講解了JavaScript語言的核心,展示了現有規范及實現為開發Web應用提供的各種支持和特性。本書主要內容包括:

          · 解讀JavaScript實現各個組成部分;

          · 闡述JavaScript面向對象編程;

          · 剖析DOM、BOM及瀏覽器事件模型;

          · Web應用基本數據格式JSON、XML及其存取;

          · Ajax、Comet服務器端通信和基于File API的拖放式文件上傳;

          · ECMAScript 5定義的新核心語言特性;

          · HTML5涵蓋的表單、媒體、Canvas(包括WebGL);

          · Selectors、Web、Workers、地理定位及跨文檔傳遞消息等新API;

          · 離線應用及客戶端存儲(包括IndexedDB);

          · 維護、性能、部署相關的開發實踐;

          · 新興API及ECMAScript Harmony展望。

          作為JavaScript技術經典名著,《JavaScript高級程序設計(第3版)》可以說是JavaScript最權威的入門書籍了


          《JavaScript DOM編程藝術(第2版)》

          推薦指數:☆☆☆☆


          作者:[英]Jeremy Keith [加]Jeffrey Sambells 譯者:楊濤 王建橋 楊曉云等

          本書是超級暢銷書的升級版,由倡導Web標準的領軍人物執筆,揭示了前端開發的真諦,是學習JavaScript和DOM開發的必讀之作。本書主要內容包括:

          · JavaScript和DOM的基本知識;

          · 通過幾個實例演示了專業水準的網頁開發技術;

          · 透徹闡述了平穩退化等一批至關重要的JavaScript編程原則和實踐;

          · 全面探討了HTML5以及jQuery等JavaScript庫。

          通過閱讀本書,讀者將看到JavaScript、HTML5和CSS如何協作來創建易用的、與標準兼容的Web設計,以及掌握使用JavaScript和DOM通過客戶端動態效果和用戶控制的動畫來加強Web頁面的必備技術;同時,還將對如何利用庫提高開發效率有全面深入的理解。


          《你不知道的JavaScript》

          推薦指數:☆☆☆☆☆


          作者:[美]Kyle Simpson 譯者:趙望野 梁杰

          本書深入理解語言內部的機制,全面介紹了JavaScript中常被人誤解和忽視的重要知識點。

          · 《你不知道的JavaScript(上卷)》介紹了該系列的兩個主題——"作用域和閉包"以及"this和對象原型"。掌握了這些知識之后,無論什么技術、框架和流行詞語,你都能輕松理解。本書講解通透深入,是入門必備書籍

          · 《你不知道的JavaScript(中卷)》主要介紹了類型、語法、異步和性能。

          · 《你不知道的JavaScript(下卷)》主要介紹了入門知識和對ES6及未來發展趨勢的展望。

          本書既適合JavaScript語言初學者閱讀,又適合經驗豐富的JavaScript開發人員深入學習。


          《Head First JavaScript程序設計》

          推薦指數:☆☆☆☆


          作者:[美]Eric T. Freeman [美]Elisabeth Robson 譯者:袁國忠

          · 本書語言和版式活潑,內容講解深入淺出,是難得的JavaScript入門書;

          · 本書內容涵蓋JavaScript的基本知識以及對象、函數和瀏覽器文檔對象模型等高階主題;

          · 書中配備了大量有趣的實例、圖示和練習,讓讀者輕輕松松掌握JavaScript。

          本書的讀者對象為JavaScript入門讀者以及網頁設計入門者。

          `````````

          進階

          《JavaScript忍者秘籍 第2版》

          推薦指數:☆☆☆☆☆


          作者:[美]John Resig [美]Bear Bibeault [美]Josip Maras 譯者:一心一譯前端小組

          本書共分4個部分,從不同層次講述了逐步成為JavaScript高手所需的知識:

          · 本書從JavaScript語言及重要的特性談起,由淺入深地探討了函數、作用域、閉包、生成器函數、對象、數組、模塊化、JavaScript與Web頁面的交互以及事件等主題;

          · 引導讀者更加深入地了解JavaScript的方方面面,充分展示了JavaScript語言的各種特性;

          · 本書結合ECMAScript 6和7的相關概念,涵蓋了流行的JavaScript框架所使用的技術。

          本書適合具備一定JavaScript基礎知識的讀者閱讀,也適合從事程序設計工作并想要深入探索JavaScript語言的讀者閱讀。


          《JavaScript設計模式》

          推薦指數:☆☆☆☆


          作者:張容銘

          本書共分六篇四十章:

          · 討論了幾種函數的編寫方式,體會JavaScript在編程中的靈活性;

          · 講解了面向對象編程的知識,其中討論了類的創建、數據的封裝以及類之間的繼承;

          · 探討了各種模式的技術,如簡單工廠模式,包括工廠方法模式、抽象工廠模式、建造者模式、原型模式、單例模式,以及外觀模式,包括適配器模式。

          · 講解了幾種適配器、代理模式、裝飾者模式和MVC模式,討論了如何實現對數據、視圖、控制器的分離。

          · 在講解MVP模式時,討論了如何解決數據與視圖之間的耦合,并實現了一個模板生成器;

          · 講解MVVM模式時,討論了雙向綁定對MVC的模式演化。

          本書幾乎包含了關于JavaScript設計模式的全部知識,是進行JavaScript高效編程必備的學習手冊。


          《JavaScript面向對象精要》

          推薦指數:☆☆☆☆☆


          作者:[美]Nicholas C.Zakas 譯者:胡世杰

          全書共6章,內容簡潔而精妙,關注面向對象的原理和ES5對象新特性,幫助那些已經熟知面向對象編程的讀者掌握這些概念是如何在JavaScript中工作的。

          · 本書深入探討了原始類型和引用類型、函數、對象、構造函數和原型對象、繼承和對象模式等主題和特性;

          · 你將學到JavaScript獨特的面向對象的編程方式;

          · 你將學到拋棄類的概念和基于類的繼承,學習基于原型的繼承和構造函數;

          · 你將學會如何創建對象、定義自己的類型、使用繼承以及其他各種操作來充分使用對象。

          總而言之,你將學到JavaScript語言并進行專業編程所需熟知的一切。本書適合熟悉面向對象編程的概念并希望將其應用于JavaScript的開發者閱讀,也適合JavaScript新手學習參考。


          《鋒利的jQuery(第2版)》

          推薦指數:☆☆☆☆


          作者:單東林 張曉菲 魏然

          · 本書介紹了jQuery的各種函數和方法調用;

          · 讀者可以系統地掌握jQuery的選擇器、DOM操作、事件和動畫、AJAX應用、插件、jQuery Mobile、jQuery各個版本變化、jQuery性能優化和技巧等知識點,并結合每個章節后面的案例演示進行練習;

          · 本書的第8章將前7章講解的知識點和效果進行了整合,打造出一個非常有個性的網站,并從案例研究、網站材料、網站結構、網站樣式和網站腳本等方面指導讀者參與到項目建設中來。

          《鋒利的jQuery(第2版)》適合所有對jQuery技術感興趣的Web設計者和前端開發人員閱讀和參考。


          Node.js是建立在Chrome瀏覽器的JavaScript運行時基礎上,用于快速構建可擴展的網絡應用的平臺。Node旨在幫助開發者編寫異步的、事件驅動的應用。在Node中,每一個請求都是異步的,并且幾乎所有的I/O都是非阻塞的。因此,Node應用非常高效率,能夠處理的"并發"連接的數量也很龐大。

          入門

          《Node.js實戰(第2版)》

          推薦指數:☆☆☆


          作者:[英]Alex Young [美] Bradley Meck [美] Mike Cantelon [美] Tim Oxley [美] Marc Harter [美] T.J.Holowaychuk [美] Nathan Rajlich 譯者:吳海星

          · Node.js核心框架貢獻者力作 ;

          · 展示Node核心技巧 ;

          · 涵蓋前端構建系統、Web框架選擇、數據庫交互和Web程序測試與部署等全棧開發所需技術。

          本書是Node.js的實戰教程,涵蓋了為開發產品級Node應用程序所需要的一切特性、技巧以及相關理念。從搭建Node開發環境,到一些簡單的演示程序,到開發復雜應用程序所必不可少的異步編程,第2版介紹了全棧開發者所需的全部技術,可作為入門書籍。

          進階

          《深入淺出 Node.js》

          推薦指數:☆☆☆☆☆


          作者:樸靈

          《深入淺出Node.js》從不同的視角介紹了 Node 內在的特點和結構。由首章Node介紹為索引,涉及Node的各個方面,主要內容包括:

          · 模塊機制的揭示;

          · 異步I/O實現原理的展現;

          · 異步編程的探討;

          · 內存控制的介紹;

          · 二進制數據Buffer的細節;

          · Node中的網絡編程基礎;

          · Node中的Web開發;

          · 進程間的消息傳遞;

          · Node測試以及通過Node構建產品需要的注意事項。

          附錄介紹了Node的安裝、調試、編碼規范和NPM倉庫等事宜。本書適合想深入了解 Node的人員閱讀,是進階必備書籍。


          HTTP & TCP/IP

          《HTTP權威指南》

          推薦指數:☆☆☆☆☆


          作者:[美]David Gourley [美]Brian Totty [美]Marjorie Sayer [美]Sailu Reddy [美]Aushu Aggarwal 譯者:陳涓 趙振平

          本書由具有多年實踐經驗的專家編寫,通過簡潔語言和大量翔實的細節圖解幫助讀者形象地理解Web幕后所發生的事情,詳細說明了Web上每條請求的實際運行情況,主要內容包括:

          · HTTP方法、首部以及狀態碼;

          · 優化代理和緩存的方法;

          · 設計Web機器人和爬蟲的策略;

          · Cookies、認證以及安全HTTP;

          · 國際化及內容協商;

          · 重定向及負載平衡策略。

          本書深入說明了Web的工作原理,內容全面,講解細致,是HTTP協議及相關Web技術方面的著作。


          《圖解HTTP》

          推薦指數:☆☆☆☆


          作者:[日]上野 宣 譯者:于均良

          《圖解HTTP》對HTTP協議進行了全面系統的介紹,可以說是一本講解HTTP協議的神書,簡單有趣,圖文并茂,生動形象,適合入門,主要內容包括:

          · HTTP協議的發展歷史;

          · HTTP協議的結構剖析;

          · 常見通信場景及實戰案例;

          · Web安全、新技術動向等。

          讀者可通過本書快速了解并掌握HTTP協議的基礎知識。


          《圖解TCP/IP(第5版)》

          推薦指數:☆☆☆


          作者:[日]竹下隆史 [日]村山公保 [日]荒井透 [日]苅田幸雄 譯者:烏尼日其其格

          · 本書是一本圖文并茂的網絡管理技術書籍,旨在讓廣大讀者理解TCP/IP的基本知識、掌握TCP/IP的基本技能;

          · 書中講解了網絡基礎知識、TCP/IP基礎知識、數據鏈路、IP協議、IP協議相關技術、TCP與UDP、路由協議、應用協議、網絡安全等內容;

          · 引導讀者了解和掌握TCP/IP,營造一個安全的、使用放心的網絡環境。


          性能優化

          《Web性能權威指南》

          推薦指數:☆☆☆☆


          作者:[加]Ilya Grigorik 譯者:李松峰

          本書由谷歌公司高性能團隊核心成員創作,堪稱實戰經驗與規范解讀結合的產物,獲得IETF下一代HTTP協議工作組主席力薦。本書目標是涵蓋Web技術體系中應該掌握的所有網絡及性能優化知識。本書主要內容有:

          · 以性能優化為主線,從TCP、UDP和TLS協議講起;

          · 解釋了如何針對這幾種協議和基礎設施來優化應用;

          · 深入探討了無線和移動網絡的工作機制;

          · 揭示了HTTP協議的底層細節;

          · 同時詳細介紹了HTTP 2.0、 XHR、SSE、WebSocket、WebRTC和DataChannel等現代瀏覽器新增的具有革命性的新能力。

          本書適合所有Web應用及站點開發人員閱讀,包括但不限于前端、后端、運維、大數據分析、UI/UX、存儲、視頻、實時消息,以及性能工程師。


          前端框架

          當前,三大主流前端框架分別是React、Vue、Angular

          React 是一個采用聲明式,高效而且靈活的用來構建用戶界面的框架,另辟蹊徑提出了以組件化的形式重新構建頁面內容,將頁面的內容按特征分塊,然后將特定塊中的HTML、CSS、JS封裝在一起,最后用組件來構建頁面內容。

          《深入React技術棧》

          推薦指數:☆☆☆☆


          作者:陳屹

          本書從幾個維度去介紹 React:

          · 一是作為 View 庫,它怎么實現組件化,以及它背后的實現原理;

          · 二是擴展到 Flux 應用架構及重要的衍生品 Redux,它們怎么與 React 結合做應用開發;

          · 三是對 React 與 server 的碰撞產生的一些思考;

          · 四是講述它在可視化方面的優勢與劣勢。

          此外,本書非常重視實戰,每一節都有實際的例子,細節豐富,內容翔實,由淺入深,無論你是 React 初學者,還是進階人士,本書都值得一讀!本書適合有一定經驗的前端開發人員閱讀。


          Vue.js是一套構建用戶界面的漸進式框架。與其他重量級框架不同的是,Vue 采用自底向上增量開發的設計。Vue.js 自身不是一個全能框架——它只聚焦于視圖層,因此它非常容易學習,并很容易與其它庫或已有項目整合。

          《深入淺出Vue.js》

          推薦指數:☆☆☆☆


          作者:劉博文

          本書從源碼層面分析了Vue.js,主要內容有 :

          · 簡要介紹Vue.js;

          · 講解內部核心技術"變化偵測",帶領大家從0到1實現一個簡單的"變化偵測"系統;

          · 介紹虛擬DOM技術,包括虛擬DOM的原理及其patching算法;

          · 討論模板編譯技術,包括模板解析器的實現原理、優化器的原理以及代碼生成器的原理;

          · 介紹其整體架構以及提供給我們使用的各種API的內部原理,同時還介紹了生命周期、錯誤處理、指令系統與模板過濾器等功能的原理。

          360奇舞團團長月影和《JavaScript高級程序設計》譯者李松峰作序推薦,適合前端開發人員閱讀。


          Angular是一個用來構建大型應用,高性能的Web應用程序的框架;是一個完整的、從 UI、路由、Http、Socket到依賴注入、編譯、優化、測試的框架。Angular上手起來有一定難度,但其工程屬性極強,非常適合多團隊的大型項目,一旦學會,優勢很大。

          《Angular權威教程》

          推薦指數:☆☆☆☆


          作者:[美]Ari Lerner [巴西]Felipe Coury [美]Nate Murray [巴西]Carlos Taborda 譯者:Nice Angular社區

          · 本書堪稱Angular領域的里程碑式著作,幾乎涵蓋了關于Angular的所有內容;

          · 對于沒有經驗的人,本書平實、通俗的講解,遞進、嚴密的組織,可以讓人毫無壓力地登堂入室,迅速領悟新一代Web應用開發的精髓;

          · 如果你有相關經驗,那本書對Angular概念和技術細節的全面剖析,以及引人入勝、切中肯綮的講解,將幫助你徹底掌握這個框架,在自己職業技術修煉之路上更進一步。

          . MIDI 簡介

          MIDI 協議即數字音樂接口(Musical Instrument Digital Interface),是電子樂器、合成器等演奏設備之間的一種即時通信協議,用于硬件之間的實時演奏數據傳遞。MIDI 協議誕生之初希望解決的事情是通過統一通信協議讓不同樂器制造商的設備可以互相兼容,比如把 Roland 鍵盤接入 Yamaha 合成器。MIDI 協議的編碼經過拓展后也可以作為一種記錄音樂信息的文件格式,被稱為“標準 MIDI 文件格式”。

          在音樂技術研發中除了需要與音頻打交道之外,許多場景中還需要直接處理音符信息。如果說 wav 與 mp3 記錄的是音樂的物理現象,那么 MIDI 協議與 MIDI 文件則記錄的是音樂這門語言的“文字”。本文的目的是讓開發中涉及到音樂“本體”的同學可以了解這一最通用的演奏信息交互和文件存儲格式的編碼規則。同時通過對 MIDI 事件流等概念的認識,能在開發中更好地抽象自己的業務邏輯。

          1.1 MIDI 數據流 & 編碼

          和 HTTP 這類協議不同,MIDI 作為傳輸協議時所有傳遞的信息都需要被實時響應,比如一個觸鍵信息、一個效果器參數的改變都需要立刻被執行,所以其采用數據流的方式進行數據傳輸。MIDI 定義了一個 8 位的二進制數據流,許多時候我們可以使用 ASCII 碼來將其表示為 16 進制的字符用于傳輸和保存。

          對于 MIDI 標準文件格式來說,其存儲的內容也是 MIDI 產生的事件流。一段典型的 MIDI 文件長這樣:

          4D 54 68 64 00 00 00 06 00 01 00 03 01 E0 4D 54
          72 6B 00 00 00 1A 00 FF 03 03 31 32 33 00 FF 51
          03 08 7A 23 00 FF 58 04 04 02 18 08 00 FF 2F 00
          ...

          上面這個例子可能會造成一些困惑,因為 MIDI 文件確實對人類閱讀不太友好,但其編碼規則實際上是較易掌握的,下面我們就來逐步認識 MIDI 的編碼規則。

          注:在本文中,一個字節的最低有效位為第 0 位,最高有效位是第 7 位。比如在 X000 000Y 中,X 為第 7 位,Y 為第 0 位。

          1.2 MIDI 消息

          MIDI 最核心的功能是用于傳輸實時的音樂演奏信息,這些信息本質上是一條條包含了音高、力度、效果器參數等信息的指令,我們將這些指令稱之為 MIDI 消息(MIDI message)。一條 MIDI 消息通常由數個字節組成,其中第一個字節被稱為 STATUS byte,其后面有跟有數個 DATA bytes。STATUS byte 第七位為 1,而 DATA byte 第七位為 0。

          開頭的 STATUS byte 有兩個作用:一個作用是表示系統或者某個信道狀態的改變,其二個作用是確定當前 MIDI Message 的類型,MIDI 類型會確定后面 DATA byte 的數量和意義。這樣說比較空洞,下面我們舉一個例子:

          Status byte : 1100 CCCC
          Data byte 1 : 0XXX XXXX
          Status byte : 1001 CCCC
          Data byte 1 : 0PPP PPPP
          Data byte 2 : 0VVV VVVV

          第一個 STATUS byte 告訴我們這是一個進行樂器選擇的 MIDI Message(1100 為樂器選擇指令,CCCC 是信道編號)。樂器選擇的 MIDI Message 只有一條 DATA byte,而這條 DATA Byte 的數據表示選擇的樂器編號。第二條 1001 開頭的 STATUS byte 則告訴我們這是一條 Note On 類型 MIDI message,這個類型按照約定有兩個 DATA byte。

          除了向整個系統發送的 MIDI 消息, STATUS byte 通常包含了信道編號(即例子中的 CCCC),16 個信道分別從 0000 到 1111。而向整個系統發送的 MIDI 信息則以 1111 開頭,原來的信道編號變成了指令編號(比如播放指令:1111 1010,終止指令:1111 1100)。

          需要注意的是,許多時候我們會連續發送許多相同狀態的 MIDI 消息,這個時候可以省略 STATUS byte,合成器會沿用最后一個接收的 STATUS byte,被合成器記錄的狀態稱之為 MIDI RUNNING STATUS。

          總結一下:

          一條 MIDI message 由 STATUS byte 和 Data byte 構成。

          STATUS byte 以 1 開頭,DATA byte 以 0 開頭。

          STATUS byte 確定消息的類型。后面的 DATA 字節數取決于消息的類型。

          STATUS byte 通常包含信道編號,除了面向系統發送的指令。

          連續相同的 STATUS byte 可以省略。

          2. 常用 MIDI Message

          MIDI Message 不需要全部掌握,需要的時候可以直接到 MIDI 標準中查詢,日常開發中只需要了解常用的幾種 MIDI Message 即可。下面筆者介紹最常用的幾種 MIDI Message。

          2.1 NOTE ON & NOTE OFF - 音符的觸發與終止

          NOTE ON 和 NOTE OFF 是最主要的兩個 MIDI Message。當演奏者敲擊音樂鍵盤的琴鍵時發送 NOTE ON 消息,它包含了音高以及“力度”的參數。當合成器收到此消息時,它會開始以相應的音高和“力度”播放該音符。當收到 NOTE OFF 消息時,合成器會終止該音符。

          每個 NOTE ON 消息都需要相應的 NOTE OFF 消息,否則該音符將一直處于播放狀態。但打擊樂器可以只發送 NOTE ON,因為打擊樂音符會自動停止。但最好養成始終發送 NOTE OFF 的習慣,因為不同合成器對這一特性的實現可能不一樣。

          下面我們舉例說明 NOTE ON:

          Status byte : 1001 CCCC
          Data byte 1 : 0PPP PPPP
          Data byte 2 : 0VVV VVVV

          在這個例子中,1001 可以理解為 NOTE ON 事件的編碼,CCCC 是信道編號。

          PPP PPPP 表示音高值,在 General MIDI 協議中(后文會提到),通常使用 69 表示標準音 A4(440 Hz),音高值增減一,就增減一個半音。比如 60 表示 C4(中央 C), 61 表示 C#4。同樣,升高或者降低八度只需要在當前音高上增減 12 即可。

          VVV VVVV 表示速率(velocity),這個速率可以理解為敲擊鍵盤的速度,或者管樂器氣流的速度。在最基礎的合成器中,速率僅用于確定彈奏音符的力度,唯一的效果是音符音量變大或變小。總體來說,下面這張表可以作為速率和樂譜中的力度記號的對應關系參考:

          但在在一些復雜的仿真建模合成器中,速率也會影響音色。我們以 Galaxy Steinway 采樣器為例:

          圖片來源:https://zhuanlan.zhihu.com/p/19964066

          左側是小力度敲擊的頻域圖,右側是大力度敲擊的頻域圖。我們可以看到大力度敲擊不僅產生了更多的泛音,也在低頻區產生了一些噪音(木材被撞擊的聲音)。

          注:關于 velocity 可以參考附錄的介紹。

          NOTE OFF 消息和 NOTE ON 消息基本一樣:

          Status byte : 1000 CCCC
          Data byte 1 : 0PPP PPPP
          Data byte 2 : 0VVV VVVV
          

          其中 CCCC 和 PPPPPPP 含義同上。VVVVVVV 是釋放速率,可以看作是按鍵抬起的速度,這個值很少使用,通常將其設置為零。另外,在實踐中經常使用速率為 0 的 NOTE ON 消息取代 NOTE OFF 消息。

          需要額外說明的是 MIDI 協議還提供了一組 All Notes Off 消息,當某個信道接收到 All Note Off 消息之后會關閉所有還在發音的振蕩器,通常來說 All Notes Off 消息用于在演奏、播放結束后用于清理狀態,這里不多贅述。

          2.2 樂器選擇

          樂器選擇消息的格式如下:

          Status byte : 1100 CCCC
          Data byte 1 : 0XXX XXXX
          

          其中唯一的一個 DATA byte 表示樂器編號,支持 128 個不同的樂器。由于不同的軟件上存在的樂器音源并不一致,為了讓 A 設備上創建的標準 MIDI 文件在 B 設備上播放時聽起來相似,樂器廠商邊采用 General MIDI 協議來編排音源。Gerneral MIDI 通常簡寫為 GM ,它提供了一個標準化的音庫,將 128 個樂器排列成 16 個系列,每個系列有 8 個同類型的樂器,并為每個樂器分配一個特定的程序編號。GM 樂器表可以參考:

          http://www.harfesoft.de/aixphysik/sound/midi/pages/genmidi.html

          在 GM 標準下,信道 10 是保留給打擊樂器的(實際上合成器可以在任何信道上使用鼓),在這個信道上樂器編碼遵循通用 MIDI 鼓樂器列表(General MIDI drum instruments list),具體可以參考:

          https://en.wikipedia.org/wiki/General_MIDI#Percussion

          由于鼓是總體上是噪音樂器,所以之前的音高參數則被映射為不同的鼓音效。

          注:噪音樂器指沒有明確音高的樂器,有明確音高的樂器稱為樂音樂器。

          2.3 控制器消息

          MIDI 設備通常會提供一些控制器用于改變合成器的某個參數,比如混響、增益等。MIDI 協議可以使用控制器消息操作 128 個不同的控制器,控制器消息結構如下:

          Status byte : 1011 CCCC
          Data byte 1 : 0NNN NNNN
          Data byte 2 : 0VVV VVVV
          

          其中 NNN NNNN 是控制器的編號,VVV VVVV 則是控制器的值。

          控制器消息一方面可以用于改變合成器的某些參數,比如我們可以用以下指令將某個信道的力度值設置為 100:

          Status byte : 1011 CCCC
          Data byte 1 : 0000 0111
          Data byte 2 : 0110 0100
          

          另一方面,控制器編碼可以通過“組合”的方式實現一些更復雜的指令。如前文所述,選擇樂器可以通過 1000 開頭的 STATUS byte 實現,這個指令可以選擇 128 種樂器。對于同一個樂器來說可以應用不同的音色庫,比如我可以在鋼琴上使用雅馬哈的采樣、施坦威的采樣或者是珠江的采樣,由于樂器廠商認為 128 這個數量對于音色庫太小了,所以采用的 MSB + LSB 的方式表示音色庫,例子如下:

          Status byte : 1011 CCCC
          Data byte 1 : 0000 0000   // 0 = Sound bank selection (MSB)
          Data byte 2 : 0000 0101
          
          Status byte : 1011 CCCC
          Data byte 1 : 0010 0000   // 32 = Sound bank selection (LSB)
          Data byte 2 : 0000 0001
          
          Status byte : 1100 0000
          Data byte 1 : 0000 0010

          這段代碼選擇了一個編號為 2,并且音色編號為 MSB = 0, LSB = 32 的樂器。由于 MSB 和 LSB 的范圍都是 2 ^ 7 = 128,所以理論上可以選擇的音色為 (2 ^ 7) ^ 2 = 16384

          在 MIDI 中控制器消息和音源與效果器的參數密切相關,不同編號的控制器有一些約定俗稱的含義,在程序中實現控制器時盡量與已有的規范對齊,具體內容可以參考這個表格:MIDI CC List(https://professionalcomposers.com/midi-cc-list/)

          注:MSB 指最高有效字節(most significant byte),LSB 指最低有效字節(least significant byte)。一個 14 位的數據 XXX XXXX YYY YYYY 可以用 MSB + LSB 表示為:0XXX XXXX 0YYY YYYY

          2.4 彎音消息

          彎音消息也用到了我們剛才提到的 MSB + LSB 表示法,其消息結構如下:

          Status byte : 1110 CCCC
          Data byte 1 : 0LLL LLLL
          Data byte 2 : 0MMM MMMM

          其中 LLL LLLL 表示 LSB,MMM MMMM 表示 MSB,彎音值 0x2000(即 0b10000000000000)為同音高,0x3FFF(即 0b11111111111111)表示上方大二度,0x0000(即 0b00000000000000)表示下方大二度。在實踐中,我們可以通過連續發送遞增或者遞減的彎音消息來表現滑音。

          2.5 系統獨占消息

          所有系統消息都以 1111 開頭,其中有兩個特殊的消息。一個是 1111 0000 它表示后面的消息是系統獨有的。另外一個 1111 0111 則表示系統獨有消息結束,消息結構如下:

          11110000
          0iiiiiii
          0ddddddd
          ..
          ..
          0ddddddd
          11110111
          

          當合成器監聽到 1111 0000 時,檢查下一個字節 0iii iiiiiii iiii 是一個 7 位的制造商 ID。如果合成器識別出這個代碼則會繼續監聽后面的數據,否則則忽略掉收到的消息,直到結束消息 1111 0111 出現。

          3. 宿主的 MIDI API

          許多宿主環境都提供了用于編寫 MIDI 交互程序的 API,在瀏覽器上是 Web MIDI API,在 iOS & Mac 上是 Core MIDI,Android 上則有 AMidi。為了方便讀者進行實際操作,我們以 Web MIDI API 為例展示如何編寫一個最基本的 MIDI 程序:

          const button = document.getElementById('console-message')
          
          button.addEventListener('click', () => {
            if (navigator.requestMIDIAccess) {
              navigator.requestMIDIAccess()
                .then(success, failure);
            }
          })
          
          function success (midiAccess) {
              const inputs = midiAccess.inputs.values();
              for (let input of inputs) {
                  input.value.onmidimessage = onMIDIMessage;
              }
          }
          
          function failure () {
              console.error('No access to your midi devices.')
          }
          
          function onMIDIMessage (messageEvent) {
            console.log(messageEvent)
          }
          

          在這里,我們可以通過 requestMIDIAccess 向用戶索要訪問 MIDI 設備的權限,用戶允許后我們會拿到一個 midiAccess 對象,可以通過這個對象拿到所有的輸入和輸出設備。我們可以通過設備對象提供的 onmidimessage 回調監聽 midi message。

          MIDI 消息的編碼存儲在 messageEvent 的 data 成員中,通過打印出的信息我們可以發現 Web MIDI API 并不會省略 Status Byte,這是為了便于開發者更容易區分指令屬于哪個狀態,而不必手動保存 MIDI 的運行狀態。

          如果想要 MIDI 可以發音,我們可以使用 Web Audio API 提供的振蕩器:

          const button = document.getElementById('play-sound')
          const oscillators = {};
          let context
          
          
          button.addEventListener('click', () => {
            context = new AudioContext()
          
            if (navigator.requestMIDIAccess) {
              navigator.requestMIDIAccess()
                .then(success, failure);
            }
          })
          
          function success (midiAccess) {
              const inputs = midiAccess.inputs.values();
          
              for (let input of inputs) {
                  input.onmidimessage = onMIDIMessage;
              }
          }
          
          function failure () {
              console.error('No access to your midi devices.')
          }
          
          function onMIDIMessage (message) {
              const frequency = midiNoteToFrequency(message.data[1]);
          
              // midi 鍵盤的普通按鍵默認使用通道 0,所以其 note on 事件為 1100 0000
              if (message.data[0] === 144) {
                  playNote(frequency);
              }
              
              // note off
              if (message.data[0] === 128) {
                  stopNote(frequency);
              }
          }
          
          function midiNoteToFrequency (note) {
              return Math.pow(2, ((note - 69) / 12)) * 440;
          }
          
          function playNote (frequency) {
              oscillators[frequency] = context.createOscillator();
              oscillators[frequency].frequency.value = frequency;
              oscillators[frequency].connect(context.destination);
              oscillators[frequency].start(context.currentTime);
          }
          
          function stopNote (frequency) {
              oscillators[frequency].stop(context.currentTime);
              oscillators[frequency].disconnect();
          }
          

          我們可以使用這個小程序來回顧與驗證我們之前講到的 MIDI Message 知識。

          這里有一個筆者以前做的視唱練耳小工具,可以使用 MIDI 鍵盤進行視唱練耳練習:

          演示地址:muse-training(https://muse-training-8gwn0lc039762917-1252681582.tcloudbaseapp.com/)

          倉庫地址:https://github.com/lipd/muse-training

          4. 標準 MIDI 文件格式規范

          MIDI 協議解決的是音樂設備之間的即時通訊問題,它本質上是一個硬件之間的通信協議。而當我們想把 MIDI 演奏保存在磁盤上則需要用到標準 MIDI 文件格式規范(Standard MIDI-File Format Spec)。和 MIDI 通信協議一樣,MIDI 文件也是 8 位字節流,下文將會說明 MIDI 文件一些最基本的格式規范。

          4.1 Chunk

          Chunk 是構成 MIDI 文件的基本單元。一個 Chunk 由三個部分組成:Chunk 類型 、Chunk 長度以及 Chunk 數據。Chunk 類型是 4 個 ASCII 字符,之后使用 32 位表示 Chunk 數據的長度,最后才是 Chunk 需要存儲的數據。

          MIDI 中一共有兩種 Chunk,分別為 Header Chunk 和 Track Chunk。Header Chunk 標記為 MThd,存儲的是整個 MIDI 文件的基本信息,和 PNG 等文件的 Header Chunk 類似。Track Chunk 標記為 MTrk,每個 Track Chunk 都存儲了一個 MIDI 事件流,一個事件流可以包含 16 個 MIDI 信道的消息。一個典型 MIDI 文件的結構如下:

          MThd <length>
          <MThd data>
          MTrk <length>
          <MTrk data>
          MTrk <length>
          <MTrk data>

          4.2 Header Chunk

          MIDI 文件的 Header Chunk 包含的信息非常簡單,我們以上面這個文件為例:

          4D 54 68 64    // MThd 的 ASCII 碼
          00 00 00 06    // MThd 的數據長度,MThd Data 固定為 6 字節
          ---- DATA 部分 ----
          00 01          // MIDI 文件格式,有 0、1、2 三種
          00 02          // MIDI 文件的包含的音軌數量,即 Track Chunk 數量
          00 DC          // MIDI 文件的時間類型

          前兩條數據已經介紹過,這里不再贅述。我們來解釋一下 MIDI 文件格式與 MIDI 時間類型:

          MIDI 文件格式(MIDI File Formats)

          MIDI 文件格式分為三種,格式 0 的 MIDI 文件只有一個 Header Chunk 和一個 Track Chunk。對于只有一個軌道的程序可以采用這種格式。

          格式 1 有一個 Header Chunk ,和多個 Track Chunk 。其中第一條 Track Chunk 是特殊的,負責記錄 MIDI 文件的所有 Meta Event(后面會講到),而從第二條 Track Chunk 開始才會記錄 MIDI Event,所以我們上圖中的 MIDI 文件實際上只有一條用于演奏的音軌。目前絕大部分的支持多音軌的程序都采用這種格式,筆者也建議讀者盡量使用這種格式。

          格式 2 的 MIDI 文件也有多個 Track Chunk,但不同的是格式 1 所有 Track Chunk 共用一條時間軸,所有 Track 應當被視作同時播放的。而格式 2 中 Track Chunk 都有自己獨立的時間信息,這種格式非常少見,不建議使用。

          我們用一張表總結一下:


          音軌數量

          時間軸

          格式 0

          1 個

          1 條

          格式 1

          多個

          1 條

          格式 2

          多個

          多條

          MIDI 時間類型

          MIDI 時間類型主要有兩種,為了方便介紹讀者可以簡單將其理解為“按音符分割的”和“按幀分割的”:

          “按音符分割的”時間類型 15 位為 0,被稱為 TPQN(Ticks Per Quarter-Note),即一個四分音符中包含了多少 Tick。在前文的例子中 00 DC 表示 TPQN 為 220,那么一個八分音符為 110 Ticks,一個二分音符為 440 Ticks。另外 TPQN 也被稱為 Pulses Per Quarter-Note (每四分音符的脈沖數),如果你在代碼中看到 PPQ、PPQN 這樣的簡寫,你知道他們是一個意思即可。

          “按幀分割的”時間類型 15 為 1,這種格式單純 MIDI 文件中幾乎不用而且比較復雜,建議讀者跳過。其編碼規則簡單說就是使用了 SMPTE 時間碼的規范。其 14 - 8 位包含了包含 -24、-25、-29 或 -30 四個值之一,對應于四種標準 SMPTE 時間碼格式(-29 對應于 30 個丟幀),并表示每秒的幀數。第 7 到 0 位表示幀內分辨率。我們依然用一張表總結一下:


          15 位

          14-8位

          7-0位

          按音符

          0

          四分音符的Tick數

          按幀

          1

          SMPTE格式

          每幀Tick數

          4.3 Track Chunk

          Track Chunk 的主要功能是用于存儲實際的演奏數據。它的 Chunk Data 中存儲的是一串事件流,被 Track Chunk 記錄的事件我們稱為 MTrk 事件,其結構如下:

          <MTrk event> = <delta time> <event>

          在這個結構中,事件可以指代三類事件:midi 事件、系統獨有事件、元事件:

          <event> = <midi event> | <sysex event> | <meta event>

          delta time

          MIDI 通信時所有信息都是即時執行,所以 MIDI 消息并沒有記錄時間,但是 MIDI 文件則需要記錄時間在時間軸上的位置。MIDI 文件采用差量時間來記錄 MIDI 事件,即 Δt。delta time 表示的是當前事件與上一個時間相差的 Tick 數。如果要表示同時發生的數個任務,則記錄一串 delta time 為 0 的事件流即可。比如我們控制器一章中切換樂器的事件流可以表示為:

          Delta time  : 0000 0000
          Status byte : 1011 CCCC
          Data byte 1 : 0000 0000   // 0 = Sound bank selection (MSB)
          Data byte 2 : 0000 0101
          
          Delta time  : 0000 0000
          Status byte : 1011 CCCC
          Data byte 1 : 0010 0000   // 32 = Sound bank selection (LSB)
          Data byte 2 : 0000 0001
          
          Delta time  : 0000 0000
          Status byte : 1100 0000
          Data byte 1 : 0000 0010

          sysex event

          即系統獨占的消息事件,具體可以參考前文中的系統獨占消息。

          meta event

          所有元事件以 1111 1111 開頭,這個指令在 MIDI 消息中表示系統復位。這個指令是一個系統實時信息,通常在使用 MIDI 文件的程序并不會用到,所以在這里用于表示元事件。元事件主要用于指定拍號、調號、速度等。

          需要注意的是FF 2F 00 是一個特殊的元事件,表示軌道結束。所有 Track Chunk 都以這個元事件結束。下面這張表是標準中已定義的元事件:


          意義

          FF 00 02

          序列號

          FF 01 len text

          文本事件

          FF 02 len text

          版權聲明

          FF 03 len text

          軌道名稱

          FF 04 len text

          軌道中使用的樂器類型

          FF 05 len text

          歌詞

          FF 06 len text

          某個點的名稱,比如“第一樂章”

          FF 07 len text

          Cue Point 某個舞臺事件描述

          FF 20 01 cc

          MIDI 通道前綴

          FF 2F 00

          End of Track

          FF 51 03 tttttt

          設置速度

          FF 54 05 hr mn se fr ff

          SMPTE Offset

          FF 58 04 nn dd cc bb

          拍號

          FF 59 02 sf mi

          調號

          5. MIDI 協議的缺陷與改良方案

          5.1 MIDI 2.0 & MPE

          MIDI 通信協議目前看來主要有兩個較明顯的缺陷。第一個缺陷是許多值可以表示的范圍實在有限,比如 note off 的 velocity 就只有 128 個、樂器也只有 128 個、只有 16 個信道。

          另一個問題更為麻煩,MIDI 中控制器、和彎音消息只能發送給某個信道,你根本就沒法將它和某個音聯系在一起。這一局限在以前并沒有引起多少問題,因為傳統樂器很少碰到按音處理控制器的情況。而彎音用得最頻繁的更多是單聲部樂器。

          但電子音樂界向來不缺乏整活健將,工程師總是會想方設法突破現有限制。最典型的例子就是 seaboard 鍵盤,這玩意兒可以在每個鍵上提供彎音能力。你可以從下面這段演奏上感受到這一樂器的神奇魅力:

          原視頻鏈接:https://www.youtube.com/watch?v=6SCug5kUsBs

          為了解決讓控制器消息能按“音”發送,seaboard 的制造商 ROLI 制訂了 MIDI Polyphonic Expression(MPE,MIDI 復音表示法)。其原理基本上可以概括為:讓每個發聲的音符都會在其 Note On 和 Note Off 之間臨時分配一個 MIDI 通道。這樣便把控制器消息和彎音消息與特定音符建立了聯系,并且很好的兼容了 MIDI 協議。

          上述問題現在都正在通過新的 MIDI 2.0 得到解決,在 MIDI 2.0 中 volocity 從 0 - 128 擴展到 0 - 65535,信道從 16 個增加到 256 個,同時 MIDI 2.0 也支持 MPE 以及遠程控制。

          5.2 如何拓展 MIDI

          如果 MIDI 2.0 和 MPE 這類現成的解決方案無法滿足你的需求,那么你可以考慮自己來拓展 MIDI 協議或者 MIDI 標準格式。目前來看,可靠的拓展方式有幾下幾種:

          1. 使用未定義的 MIDI 消息:比如系統消息 1111 0101 的行為在 MIDI 標準中就未被定義。這種方法的好處是不需要進行額外的解析工作,但缺點便是可以使用的指令十分有限。
          2. 使用自定義 Chunk:Chunk 在設計之初便考慮到了拓展的問題,你可以按照 Chunk 的格式自由地聲明一個新的 Chunk 類型,主流解析工具在碰到無法解析的 Chunk 時會自動忽略掉,所以不用擔心兼容的問題。如果你有整段的數據,既不屬于 Track,又不能被 Heaer 所包含,那么可以考慮這種方式。
          3. 使用系統獨占消息:如果你需要在 MIDI 通信協議上進行拓展,可以考慮使用系統獨占消息,合成器會自動忽略無法解析的獨占消息。具體可以參考附錄中的系統獨占消息一節。
          4. 其他:你也可以參考 MPE 的方式,基于現有的編碼方案但是重新定義指令的意義和執行。

          6. 思考與討論

          6.1 什么時候使用 MIDI 格式,什么時候不用?

          首先我們需要認識到 MIDI 的優點,MIDI 記錄的實際上是事件流,最適合的場景就是在現場演奏時用于硬件之間的通信。作為 MIDI 文件格式作為一種存儲格式,其優點是數據十分緊湊,體積較小。但 MIDI 的缺點是十分明顯的,一方面我們無法快速查詢、訪問其中某個具體內容的值:比如我們沒法快速找到某一個軌道的拍號,或者某個音的音高。

          所以我的建議是,盡量避免在現場演奏場景之外使用 MIDI 文件格式,但可以在抽象上對齊 MIDI。在內存中我們盡量把 MIDI 文件轉化為實例對象,便于我們快速訪問。在需要持久化的場景下則可以使用更容易解析的 JSON 或者 MusicXML 格式。只有在用戶需要或者向其他編輯工具導出數據的時候,我們才考慮使用 MIDI 標準文件格式。

          6.2 MIDI 協議無法滿足的需求如何解決?

          絕大部分這類問題可以通過不使用 MIDI 編碼來解決。原則很簡單,只要不涉及現場演奏場景和向其他工具導出數據,就避免使用 MIDI 編碼來做任何事情。只用確保在需要 MIDI 的場景可以導出 MIDI 文件就行。

          6.3 如果多數場景不使用 MIDI,那有必要深入學習 MIDI 協議嗎?

          如果你的開發工作涉及到音樂的“本體”部分,那么我建議多了解一些 MIDI 協議,因為雖然我們可能多數情況下不直接使用 MIDI 協議的編碼,但是 MIDI 的事件流是創作場景和存儲場景會大量用到的,同時 MIDI 中的多數抽象和概念是行業內通用的。

          6.4 如何設計自定義的音樂數據格式?

          我的建議是用一個文檔維護所有的基礎字段和拓展字段,各項目在定義 Model 時盡量參考這個文檔。如果現有的拓展字段可以解決你的需求,就不要新增拓展字段。

          附錄

          可變長度數量(Variable-Length Quantities)

          由于單個字節表示的最大范圍為 0 - 256,所以在 MIDI 文件中表示較大數字時會采用可變長度數量。其每一個字節使用第 7 位表示這個字節是否為最后一個字節,1 表示不是最后一個字節,0 表示是最后一個字節, 0 - 6 位則作為有效位。

          舉一個例子,數字 127 可以表示為 0111 1111 ,128 則表示為 1000 0001 0000 0000,這樣理論上可以表示的數字可以無限大,不過在實踐中通常不會使用超過 32 位。

          總結一下就是:

          7 位

          0-6 位

          是否為最后一個字節

          有效位

          速率的解釋

          note on 中的 velocity 實際上是按鍵的“觸發速率”,你可以把其視為從鍵盤能感知到下按到下按結束這個過程中的鍵程除以按下時間,note off 則是反向的“釋放速率”。速率的計算方式和更多細節可以參考這篇論文:The Interpretation of MIDI Velocity

          一堆速查表

          • 查十進制的 MIDI 消息:Expanded MIDI 1.0 Messages List (Status Bytes)
          • 查 GM 樂器表:General MIDI Instrument List
          • 查 MIDI 事件流:Standard MIDI-File Format Spec. 1.1, updated

          參考文獻

          • https://www.midi.org/specifications
          • MIDI Tutorial
          • Standard MIDI-File Format Spec. 1.1, updated
          • MIDI Polyphonic Expression (MPE) Specification Adopted
          • 鋼琴的觸鍵方式是如何影響彈出來的音色的?(https://zhuanlan.zhihu.com/p/19964066)
          • MIDI Tick、Meta-event、變長數表示法、區分 MIDI 文件中單個字節的含義(https://www.cndzq.com/bbs/thread-117332-1-1.html)
          • MPE in Live 11(https://help.ableton.com/hc/en-us/articles/360019144999-MPE-in-Live-11)
          • GDX-620 使用說明書(https://de.yamaha.com/files/download/other_assets/9/334239/DGX-620_ZH.pdf)

          推薦讀物

          • 《音樂聲學——音響、樂器、計算機音樂、MIDI、音樂廳聲學原理及應用》- 龔鎮雄
          • The Computer Music Tutorial - Curtis Roads

          分享成果,隨喜正能量】行走于塵世,繁忙的工作節奏,沉重的生活壓力,似乎想讓生活過得行云流水,真的不是一件容易的事情,那么何不讓它變得簡單一些?或許我們不夠時尚,至少我們可以簡約,或許我們不夠精致,至少我們可以簡潔。把每一段旅途,都當做最好的修行;把每一段旅途遇到的困難,都當做自己的助力;把每一段旅途中遇到的人,都當做今生的因緣。

          《VBA信息獲取與處理》教程是我推出第六套教程,目前已經是第一版修訂了。這套教程定位于最高級,是學完初級,中級后的教程。這部教程給大家講解的內容有:跨應用程序信息獲得、隨機信息的利用、電子郵件的發送、VBA互聯網數據抓取、VBA延時操作,剪貼板應用、Split函數擴展、工作表信息與其他應用交互,FSO對象的利用、工作表及文件夾信息的獲取、圖形信息的獲取以及定制工作表信息函數等等內容。程序文件通過32位和64位兩種OFFICE系統測試。是非常抽象的,更具研究的價值。

          教程共兩冊,八十四講。今日的內容是專題六“VBA中利用XMLHTTP完成網抓數據”的第1講:XMLHTTP的簡單講解

          第一節 XMLHTTP的簡單講解及相關概念的介紹

          現在的社會是網絡的社會,離開了網絡,很多工作會變得不通暢。我們日常的生活也是和網絡緊密聯系一起的,那么網絡是如何搭建的呢?我們可以通過本講的講解了解到HTTP 超文本傳輸協議,TCP/IP的介紹,XMLHTTP的介紹,等等。

          1 什么是XMLHTTP,它是用來做什么的?

          1) XML的介紹 XML指可擴展標記語言(EXtensible Markup Language),設計宗旨是傳輸數據,是W3C (萬維網聯盟World Wide Web Consortium)的推薦標準。XML 是各種應用程序之間進行數據傳輸的最常用的工具,并且在信息存儲和描述領域變得越來越流行。

          2) HTTP的介紹 HTTP 超文本傳輸協議(HyperText Transfer Protocol,超文本傳輸協議)是因特網上應用最為廣泛的一種網絡傳輸協議,所有的WWW文件都必須遵守這個標準。

          HTTP是一個基于TCP/IP通信協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。

          3) TCP/IP的介紹 TCP/IP是供已連接因特網的計算機進行通信的通信協議(Transmission Control Protocol / Internet Protocol)。定義了電子設備(比如計算機)如何連入因特網,以及數據如何在它們之間傳輸的標準。

          TCP 用于應用程序之間的通信。當應用程序希望通過 TCP 與另一個應用程序通信時,它會發送一個通信請求。這個請求必須被送到一個確切的地址。在雙方“握手”之后,TCP 將在兩個應用程序之間建立一個全雙工 (full-duplex) 的通信。這個全雙工的通信將占用兩個計算機之間的通信線路,直到它被一方或雙方關閉為止。

          IP 用于計算機之間的通信。IP 是無連接的通信協議。它不會占用兩個正在通信的計算機之間的通信線路。這樣,IP 就降低了對網絡線路的需求。每條線可以同時滿足許多不同的計算機之間的通信需要。通過 IP,消息(或者其他數據)被分割為小的獨立的包,并通過因特網在計算機之間傳送。IP 負責將每個包路由至它的目的地。

          TCP/IP協議意味著 TCP 和 IP 在一起協同工作。TCP 負責應用軟件(比如你的瀏覽器)和網絡軟件之間的通信。IP 負責計算機之間的通信。TCP 負責將數據分割并裝入 IP 包,然后在它們到達的時候重新組合它們。IP 負責將包發送至接受者。

          4) XMLHTTP的介紹 XMLHTTP是一套可以在Javascript、VbScript、Jscript等腳本語言中通過http協議傳送或從接收XML及其他數據的一套API。XmlHttp最大的用處是可以更新網頁的部分內容而不需要刷新整個頁面。

          來自MSDN的解釋:XmlHttp提供客戶端同http服務器通訊的協議。客戶端可以通過XmlHttp對象(MSXML2.XMLHTTP.3.0)向http服務器發送請求并使用微軟XML文檔對象模型Microsoft? XML Document Object Model (DOM)處理回應。

          現在的絕對多數瀏覽器都增加了對XmlHttp的支持,IE中使用ActiveXObject方式創建XmlHttp對象,其他瀏覽器如:Firefox、Opera等通過window.XMLHttpRequest來創建xmlhttp對象.

          2 應用XMLHTTP抓取數據的步驟

          1)創建XMLHTTP對象 //需MSXML4.0支持

          2)打開與服務端的連接,同時定義指令發送方式,服務網頁(URL)和請求權限等。客戶端通過Open命令打開與服務端的服務網頁的連接。與普通HTTP指令傳送一樣,可以用"GET"方法或"POST"方法指向服務端的服務網頁。 

          3)發送指令。 

          4)等待并接收服務端返回的處理結果。 

          5)釋放XMLHTTP對象

          3 XMLHTTP的屬性及方法

          1) XMLHTTP的常見屬性: 

          onreadystatechange:在同步執行方式下獲得返回結果的事件句柄。只能在DOM中調用。 

          responseBody:   結果返回為無符號整數數組。 

          responseStream:  結果返回為IStream流。 

          responseText:   結果返回為字符串。 

          responseXML:   結果返回為XML格式數據。

          2) XMLHTTP的常用方法: 

          ① Open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword)創建一個新的http請求,并指定此請求的方法、URL以及驗證信息(用戶名/密碼)打開指定網址

          bstrMethod:  數據傳送方式,即GET或POST。 

          bstrUrl:    服務網頁的URL。 

          varAsync:   是否同步執行。缺省為True,即同步執行,但只能在DOM中實施同步執行。用中一般將其置為False,即異步執行。 

          bstrUser:    用戶名,可省略。 

          bstrPassword:用戶口令,可省略。 

          setRequestHeader(bstrHeader, bstrvalue)

          bstrHeader:HTTP 頭(header) 

          bstrvalue: HTTP 頭(header)的值 

          如果Open方法定義為POST,可以定義表單方式上傳: 

          xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") 

          ② Send(varBody)發送請求到http服務器并接收回應

          varBody:指令集。可以是XML格式數據,也可以是字符串,流,或者一個無符號整數數組。也可以省略,讓指令通過Open方法的URL參數代入。

          ③ abort 取消當前請求

          ④ getAllResponseHeaders 獲取響應的所有http頭

          ⑤ getResponseHeader 從響應信息中獲取指定的http頭

          以上我給出了一些常用的屬性和方法,其他的大家可以參考相關的資料,或許我在今后的課程中會用到時講解。同時我們還要主要下面的注意點:

          1、ResponseBody是二進制的數據,是服務器傳來的沒有經過任何加工的數據。

          2 ResponseText是按照utf-8編碼把ResponseBody轉換而成,也就是:ResponseText=ByteToStr(ResponseBody,"UTF-8")

          本節知識點回向:了解一些概念,HTTP,TCP/IP,XMLHTTP,以及XMLHTTP的常用屬性和方法。

          我20多年的VBA實踐經驗,全部濃縮在下面的各個教程中,教程學習順序:


          主站蜘蛛池模板: 日本中文字幕一区二区有码在线| 成人在线一区二区| jizz免费一区二区三区| 国产天堂在线一区二区三区| 日韩精品无码免费一区二区三区| 一区二区三区四区精品视频| 精品人妻无码一区二区三区蜜桃一 | 自慰无码一区二区三区| 少妇特黄A一区二区三区| 韩国理伦片一区二区三区在线播放| 国产大秀视频在线一区二区| 亚洲AV无码一区东京热久久| 国产高清视频一区二区| 国产探花在线精品一区二区| 亚洲Av无码国产一区二区| 日韩高清一区二区三区不卡| 香蕉一区二区三区观| 国产一区二区三区小向美奈子| 小泽玛丽无码视频一区| 亚洲成AV人片一区二区密柚 | 亚洲一区二区三区国产精品| 日韩精品无码一区二区三区四区| 一区二区三区美女视频| 国产福利一区二区三区视频在线| 免费av一区二区三区| 国产一区二区视频免费| 伊人久久一区二区三区无码| 亚洲第一区视频在线观看 | 国产亚洲日韩一区二区三区 | 亚洲av区一区二区三| 少妇人妻精品一区二区三区| 日韩一区二区三区视频久久| 亚洲av成人一区二区三区观看在线| 日韩a无吗一区二区三区| 中文乱码精品一区二区三区| 国产福利一区二区三区在线观看 | 在线视频亚洲一区| 日韩在线不卡免费视频一区| 丝袜美腿高跟呻吟高潮一区| 精品深夜AV无码一区二区老年| 国产精品亚洲高清一区二区|