10/17~10/20,極短期計劃,麥克風錄音轉音階,修正之前理解錯誤,但效果還是不好

(function(w,d,s,l,i))(window,document,'script','dataLayer','GTM-KDKMGT');
(function(d, s, id) var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/zh_TW/all.js#xfbml=1&appId=668497826514848"; fjs.parentNode.insertBefore(js, fjs); (document, 'script', 'facebook-jssdk'));






if(BAHAID)
BAHAID = BAHAID.replace(/&/g, "&")
.replace(/, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");

BAHAIDlow = BAHAID.toLowerCase();

document.write('');

document.write('

');
document.write('');
document.write('');
document.write('');
document.write('

');

//document.write('
');
document.write('
');
document.write('
');
document.write('
');
document.write('
');
document.write('
');
document.write('
');
document.write('
');


else
document.write('
');
document.write('');
document.write('
    ');
    document.write('
  • 我要登入
  • ');
    document.write('
  • 註冊
  • ');
    document.write('
  • ');
    document.write('
');
document.write('
');


document.write('
');

document.write(' ');

(function()
var cx = 'partner-pub-9012069346306566:kd3hd85io9c';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = 'https://cse.google.com/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
)();

service = new rsearch('rsearch');

if( BAHAID )
NOTIFY_getnum();
run30 = setInterval("NOTIFY_getnum()",60000);


function insideSecondaryfunc(frm, evt){
if( 0

















breadCrumbs(122, '', 'homeuid=y541258')








    breadCrumbs_listMenu(122, 0, 'homeuid=y541258')





    創作內容





    2 GP


    10/17~10/20,極短期計劃,麥克風錄音轉音階,修正之前理解錯誤,但效果還是不好


    作者:物不平則鳴 李兒諳│2018-10-17 17:44:17│贊助:4│人氣:52



    10/20網頁麥克風錄音轉音階並存檔"(慘不忍睹),但就先這樣吧

    昨天getByteFrequencyData(dataArray),每個所記錄的0~255猜測應該是振幅大小

    陣列索引*取樣率/fftSize才是該Hz的

    程式修改下後有好些,但音還是不準(因為我還是用取振幅max為準的做法)

    https://github.com/y541258/HTML5/blob/master/MIDI_web/record_or_file_to_pitch.html



    若要改良的話~我想大概得兩段式

    一段是錄音,然後把錄音檔傳上網頁,才能慢慢分析

    (因為實時分析產生對應音階,總覺得運算速度沒那麼快)

    所以若這篇以後有更新的話

    大概就是

    1.針對傳的檔案顯示頻譜

    2.找出雜訊的頻譜特徵並過濾掉

    3.找出人聲或樂器的特徵,化為較準確的音階

    雖然對我而言

    找出頻譜特徵相關的

    我都不知道該怎麼做!!




    若要比較好用的網站,在線測音高(錄音樂檔可用Audacity或本文Go語言的方法)


    https://bideyuanli.com/pp

    會發現這網站是因為不知道頻率資料要怎麼轉成音高,找資料過程中時發現的

    意外的發現我以前其實是有看過那篇文章的(因為知乎文章點過贊同了)

    只是我現在已經沒印象了

    留言也是說沒辦法自動準確transcription扒譜

    所以沒做扒譜功能

    (其實他每個時間點的音高已經做出來了,只是沒有轉成音樂檔或文字檔記錄下來)

    那我想做的就是這個

    當然我做的肯定也是不準的

    (目前還在想要怎麼做?)




    在一番努力(誤打誤撞)之後總算有初步成果

    雖然目前感覺只能錄到雜訊

    出來的效果跟想像中的差很多

    目前算是處於根本不能用的狀態

    我試著唱歌跟喊話感覺效果也不是很好

    是有些想直接分析檔案看會不會好些

    至少現成的音訊檔大多有去躁處理

    可是我大概覺得就算用音訊檔也不會好到哪邊去

    因為我目前擷取頻率的方式是

    在一段時間中,選取頻率最高的

    因此試著錄了幾次,就算不說話也會是高音雜訊

    而現成的音訊檔許多和聲,最高的頻率估計不會很低,大概也會是一堆雜訊吧

    看樣子沒那麼容易

    可能還是要老實從pitch detection的原始碼下手





    雖然沒什麼成果

    但至少產生.ogg檔沒問題(.wav還不清楚要用什麼codec,.ogg網路有看到範例就直接用了)

    就先貼上來吧



    -----------------------10/19↓---------------------------------

    嗯,嘗試了一陣子

    在能錄音、顯示頻率資料(WebAudio的analyser.getByteFrequencyData(dataArray);)之後

    突然覺得下步有些茫然

    繼續找資料



    這方面的英文是pitch detection(音高偵測)

    但實作方式我沒看到用getByteFrequencyData()來做的



    有關getByteFrequencyData()總算找到個比較有用的了

    https://stackoverflow.com/questions/14789283/what-does-the-fft-data-in-the-web-audio-api-correspond-to/14789992#14789992

    簡單的來說

    getByteFrequencyData()的值,都介於0~255之間

    那0~255的話,是代表幾Hz頻率呢?

    要看fft的窗格大小,也就是analyser.fftSize = 2048;這樣的

    若沒寫,預設是2048

    假如fftSize是2048的話

    那getByteFrequencyData(Uint8陣列);

    會得到個1024大小的Uint8陣列(也就是fftSize/2大小的陣列)

    那取樣率要知道是多少!!

    如果是預設44100Hz的話

    44100(取樣率) / 2048(fftSize) = 21

    因此0代表0,1代表21Hz,255代表5355Hz



    附帶一提

    (自己的麥克風取樣率在這看


    )



    嗯,知道這些之後...我看我配合震盪器寫不寫得出來

    寫得出來還要看效果好不好

    但若效果不好,其實我是不知道怎麼改良的



    ----------------------




    找到個比起MIDI檔轉成WAV檔再重新組合更好的做法

    直接用Web Audio的震盪器

    詳情請看


    https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createMediaStreamDestination

    更改頻率與播放時間可用

    const G4 = 440 * Math.pow(2, -2/12);

    var t = audioCtx.currentTime;

    osc.frequency.setValueAtTime(G4, t);

    可參考這篇


    https://teropa.info/blog/2016/08/10/frequency-and-pitch.html

    雖然出來的聲音音量很穩定

    (可視為缺點也可視為優點,不過音量穩定的話,若不滿意只要自己找方法淡入淡出即可
    自己演奏的話倒很可能同個音沒辦法長時間發那麼穩定)



    麻煩了,不知道是被擋掉還是出錯的程式片段是

    ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED);

    這樣就很難救了

    go-ole是別人寫好的函式庫,還蠻龐大的

    試著

    fmt.Println("err")

    fmt.Println(err)

    有顯示字串(程式確實在這邊終止),但沒有顯示錯誤內容,很有可能是被擋掉了吧!!

    那這計劃應該是宣告失敗了

    改個目標



    昨天想了一下,昨天的目標意義不大

    因為在執行錄音程式 -o 檔名.wav時

    就會產生對應的檔名.wav

    因此若要做對網頁有用的程式

    就勢必得用WASM一類的技術

    不然程式還是全都得放在客戶端

    那昨天研究了一陣子Go語言寫WASM

    推薦看這三篇

    Go語言如何編譯成WASM與實際運作


    https://www.youtube.com/watch?v=4kBvvk2Bzis

    (在Windows底下,Go語言編譯成WASM用的是

    set goos=js

    set goarch=wasm

    較麻煩的是以後若編譯正常程式時,還要把goos跟goarch手動切回來

    以我的例子是

    正常編譯是

    set goos=windows

    set goarch=amd64)

    如何使用Javascript呼叫Go語言副程式


    https://www.linkedin.com/pulse/all-you-need-know-go-111-modules-webassembly-major-changes-tarpara

    如何傳參數


    https://www.kabuku.co.jp/developers/go-to-webassembly



    我測了一下之後

    就算有設參數

    應該是寫檔案的程式會被擋掉

    會有個Warning,然後

    exit code: 1

    我查了下,不知道exit code所代表的含意

    只知道exit code若是不等於0的話

    就是程式不正常的結束



    因此要把

    https://github.com/moutend/go-wca/tree/master/example/LoopbackCaptureSharedTimerDriven

    這裡面的main.go程式碼

    改寫成WASM可以接受的形式了

    那今天主要就是

    找出哪段程式碼要改跟要怎麼改

    我比較擔心的是,最核心的獲取電腦所播放的聲音這本身被擋掉



    -----------------------10/18↓---------------------------------

    我實在是太在意網頁錄音的可行性了

    查了一堆資料,沒找到有用的

    頂多只找到有相同問題,但沒解答的

    但看到Stackoverlow上有個有趣的提問底下的互動

    「Do you mean ...」

    忘記英文原文,意思大致上是,你的意思是用Javascript還是Node.js

    嗯,後來我想了下,純網頁應該是很難辦到,但若配合伺服端程式語言使用的話

    那應該是很有機會的

    因此稍微找了下現成的軟體用的錄音技術大概是怎麼辦到的

    後來找到

    Audacity這套軟體,是用WASAPI來達到把電腦所有音效錄下來的效果

    那WASAPI應該是個關鍵字

    我再配合我要用的語言應該就找得到

    然後我就找到了這篇!!

    "GoからWindows Core audio API使えるようにバインディングを書いた"

    https://blog.mouten.info/go%E3%81%8B%E3%82%89windows-core-audio-api%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%83%90%E3%82%A4%E3%83%B3%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%92%E6%9B%B8%E3%81%84%E3%81%9F-a592686d06ed

    哦,太棒了,有Github,README.md也寫得很好


    https://github.com/moutend/go-wca/tree/master/example/LoopbackCaptureSharedTimerDriven

    照著用測試了下,還真的可以錄下所有電腦聽得到的音效(不管有沒有麥克風都行)

    那我覺得應該是有機會做到

    "把電腦上的所有聲音(含麥克風與不含麥克風都有)錄起來
    然後轉成對應的音階,用成MIDI的聲音類型(但檔案格式是.wav)"



    因為Go語言可以利用強者 Yoshiyuki Koyanagi所提供的程式,產生出WAV檔

    那我們只要把產生出的WAV檔

    用像Web Audio這樣的Javascript內建程式庫(其實不算內建,不過有些主流瀏覽器支援)

    就可以做傅立葉轉換

    而且是快速傅立葉轉換

    或者說要是沒快速傅立葉轉換,就不會廣為被工程所使用了

    把複雜的不規則波形轉成一個個音階的單獨波形

    (有波性質的都可以用傅立葉轉換來處理,不只有聲音,只是聲音的應用比較直覺)

    也就變得像Sin、Cos那樣的波

    而知道波的頻率就相當於知道波的音階

    最難寫的快速傅立葉轉換已經有人做好了

    因此剩下的程式應該都是較不需要動腦,純費工的程式

    這樣做出來的可能性就大幅提高



    不過...

    若一定要配合伺服端語言的話

    手機就不能單獨運作寫出來的程式了

    (我不清楚手機要怎麼當Server,應該也不太適合當Server)

    而這功能

    因為有Now.in該網站的前車之鑑

    (Now.in是個線上廣播電台

    雖然該平台本身不提供音樂

    但線上點歌的,大多用的音樂是未經授權的

    因此隨著後來Now.in越來越受歡迎

    開發者因為家人人身安全受威脅

    被逼得刪除掉自己苦心經營的網站

    在Now.in被查封以前

    我還有看過Now.in網站開發者維護網頁安全

    分享怎麼發現被DDOS攻擊與解決的經過的文章

    感覺是很認真在經營網站的開發者)



    總之,也不適合租伺服器來做這功能

    因為錄下電腦所有音效這功能,不是用來錄歌,就是用來錄自己唱的歌

    那絕大多數的使用情形肯定不是原創的

    很容易有法律爭議導致被找麻煩

    因此我就純粹做著自娛自樂

    若做得順利的話開放原始碼

    但拿去用會不會出問題我就不知道了

    我也不知道Yoshiyuki Koyanagi跟Web Audio它們的程式使用上是否有什麼限制

    像是程式碼授權、是否允許商業目的使用這樣

    就僅是提醒下



    雖然說剩下來的程式應該需要動腦的成份較低

    但還是要花些時間的

    我就先去想程式接下來要怎麼寫

    我想10/18的目標

    網頁檔上按個按鈕

    然後Go語言啟動Yoshiyuki Koyanagi所寫的LoopbackCaptureSharedTimerDriven.exe

    然後再按個按鈕結束錄音

    Go語言再對執行中LoopbackCaptureSharedTimerDriven.exe送中斷訊號(Ctrl-C)

    接著再讀取WAV檔案給使用者下載


    先做到這樣就好!!



    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    附帶一提:若真的是用我上述寫的方法

    應該是想因為做網站被抓去關

    這樣拿到鐵飯碗(吃牢飯過一生)的如意算盤都打不響

    那不管有沒有租伺服器

    使用者都必須給自行當http伺服器才能用(我的做法是用Go語言,覺得這樣較省事)

    不然由伺服器執行LoopbackCaptureSharedTimerDriven.exe

    錄的也肯定是伺服器本身的音效

    因此...嗯,好吧

    最理想的狀況是純網頁

    但純網頁很可能是權限問題(安全性考量),因此應該沒辦法直接呼叫些WinAPI來做到這效果

    我目前是想不太到有什麼好方法來處理!!

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!



    不過我10/18有些事情

    且現在已經12:05了

    今天應該是蠻有可能做不出來的

    因此這雖然是10/18的目標

    但這應該也是10/19的目標!!

    只是10/19要是提早完成的話

    就可以提前進入最終目標

    把儲存的錄音檔,轉成音階,用MIDI轉出的.wav檔,組合成新的.wav檔


    這樣就能達到 簡易去人聲軟體(理論上用麥克風唱也是可以啦,就把歌曲轉純音樂) 的效果了




    ----------------------------↓10/17------------------------------

    昨天(10/16)我其實是在研究,如何用Javascript檔錄音

    但是getUserMedia()不能同時錄麥克風跟電腦的音效

    或者說是HTML5底下,還不知道能否不透過麥克風來錄電腦的音效

    (唔,理論上用立體聲混音,捨棄麥克風的聲音的話,應該是能錄電腦的音效,但我沒實際測試過)



    於是今天我又重看了.wav檔格式

    覺得"把midi.html的聲音製作成.wav檔,透過Javascript寫.wav二進位資料達成"

    這個短期計劃還算合理

    10/17,目標是,把原始的wav檔,變為播放時間兩倍長的wav檔(同樣的內容播兩遍)

    先不用程式的方法實現

    僅使用PSPad等有提供十六進位編輯器的做法直接改.wav檔內容來完成

    (其實這段我在2017/11/24左右有研究過,但是那段時間精神不是很正常就是了)



    現在根據維基百科連結

    http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html

    其中的內容

    覺得要改什麼具體清晰很多!!



    --------------10/17,修改.wav檔成功-------------------

    基本上在取樣率、取樣頻道...全不變的狀況下

    只要改這兩個橘色框框就好




    然後在綠色框框處後面複製資料,貼上兩次即可




    橘色框框處要改多少要看原檔案內容

    像我這個原檔案是



    3EBB0600

    意思是在這後面的內容長度是6BB3E個bytes


    F8BA0600

    意思是data大小是6F8BA個bytes



    讀起來比較不直覺是因為採用的endian(位元組順序)是little endian,所以要由右至左讀



    所以我們可以很清楚的知道,第一個檔案有6BB45個位元組

    (6BB3E+7=6BB45)

    而修改後兩倍大小的檔案則是D367D個位元組

    (根據圖檔,3676 0D00,也就是000D3676 + 7 = D367D)

    上述檔案具有幾位元組

    可以在十六進位編輯器中,按ctrl-end(迅速跳到檔案尾端的快速鍵),來驗證下想法



    .wav檔基本上沒有經過壓縮

    因此檔案格式很好理解

    (雖然其實有損壓縮的格式其實也長得類似這樣

    像影片檔.mp4,就是用一堆mdat這樣子的標籤接上這區塊大小的內容所組成的

    不這麼做程式不知道一次要讀幾位元組才算結束

    .wav單純的原因是

    它的音訊檔實際音訊內容所佔的大小也很好算

    雖然我目前還不會算

    應該就是 每秒取樣幾次*所使用的頻道數量*取樣一次用幾個bytes這樣



    .mp3因為會把超過人耳能感受到的頻率截掉

    雖然我也不清楚細節

    或者說我根本就不知道.mp3檔的檔案格式長怎樣

    但我猜其檔案大小就沒.wav檔那麼好估算)




    ------------------------------------------------------------------



    老實說我是很想做個網頁程式

    能夠把電腦上的所有聲音(含麥克風與不含麥克風都有)錄起來

    然後轉成對應的音階,用成MIDI的聲音類型(但檔案格式是.wav)這樣

    不過這個目標目前太過宏大

    先從簡單的做起吧!!

    我這幾天比較有空,若目標訂小點應該是有機會做出來!!

    至於如何取得網頁瀏覽者的電腦音效內容

    這個根本就不知道要用什麼函式來處理的

    就先擺在後面,也許哪天網路出現相關文章或技術是在處理這件事情的

    但在找到相關資訊前

    我想"透過網頁錄電腦上的所有聲音"

    目前對我來說是無解







    喜歡2
    收藏
    0
    引用
    0
    留言
    推上首頁



    檢舉








    引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4164889

    All rights reserved. 版權所有,保留一切權利





    相關創作




    [翻譯]艦これ-働く鹿島さんとほっぽちゃんの日常02




    【翻譯】梗圖翻譯系列-193




    【單圖】釘宮あつきー 艦これのまとめ その7




    翻譯專欄:Brandon Santiago:13 Days of ERMA-WEEN 2018 Part 2




    灰絲襪腿腿


    留言共 0 篇留言




    Util.ChangeText('replys', Util.ChangeText.FLAG_LAZYLOAD|Util.ChangeText.FLAG_MAX_SIZE|Util.ChangeText.FLAG_BALA_PLAYER);

    我要留言提醒:您尚未登入,請先登入再留言


    2喜歡★y541258 可決定是否刪除您的留言,請勿發表違反站規文字。



    前一篇:10/15,midi.h...

    後一篇:10/20,思考下一步與...








    egg('.MSG-list8C img').each(function(elem)
    elem.className = elem.className + ' lazyload';
    );

    egg('.gallery-image').imageGallery();

    function deleteCreation(vCode)
    var content = egg('.MSG-list8C').html();
    var pattern = /]*?>/i;
    var html = '
    確定要刪除嗎?';
    var width = '200px';
    if(content.match(pattern))
    html += '
    ';

    var boxConfig =
    'closeButton': false,
    'css':
    'width': width

    ;

    egg.mutbox(html, '訊息',
    '確定': function()
    if(egg('#chkDelTruthImage:checked').size())
    egg('[name=delTruthImage]').val('yes');


    egg.cookie.del('ckHOME_CREATION','home.gamer.com.tw','/');
    egg.cookie.set('ckHOME_CREATION',vCode,'home.gamer.com.tw','/');
    document.getElementById('frmDel').submit();
    egg.lightbox.close();
    ,
    '取消': function()
    egg.lightbox.close();

    ,boxConfig);

    var buttonOk = egg('.BH-popbtns :button:eq(0)');
    if(buttonOk.size())
    buttonOk.get(0).focus();



    resizeImage(627);

    egg('.btnGp').click(function()
    $.mutbox('請先登入才能進行此動作', '訊息', '確定':function()location.href='https://user.gamer.com.tw/login.php';);
    );







    訂閱私訊


    作品資料夾


    對於個人而言特別重要的 (28)


    自編遊戲綜合考題與試答 (8)


    單機版網頁遊戲系列相關 (10)

    如何改成線上版網頁遊戲系列 (6)

    自製腳本語言 (1)

    3D (1)

    格鬥遊戲 (1)

    遊戲賞析系列 (1)

    遊戲程式進展 (20)

    簡略音樂遊戲 (3)

    地水師 (5)

    多媒體素材處理 (13)

    文字型冒險遊戲 (7)

    極簡陋大富翁 (3)

    RPG迷宮與戰鬥雛形 (12)

    競技型俄羅斯方塊 (1)

    組牌遊戲 (2)

    魔喚精靈日本版─闇箏 (1)

    旋轉泡泡球(待處理) (0)

    常見網頁遊戲系統模仿 (1)

    橫版過關遊戲 (3)

    滑動式拼圖 (1)


    程式語言建立自信系列 (8)


    Unity相關 (6)


    [問題與思考] (7)


    實況、名詞、關注議題分享 (46)

    實況歌單 (1)


    音樂與自動作曲相關 (11)

    聽譜練習 (12)

    自動作曲研究 (4)


    玩遊戲感想 (21)

    電動日記(真的日記,不是遊戲名稱) (5)

    式姬-幽界之門 (19)

    うつしよの帳 (1)

    送帳號 (1)

    陰陽師 (3)


    遊戲妄想 (14)

    偶爾正經下 (2)


    對正規教育的期許 (25)


    時光旅行 (4)


    除去上述分類後還是跟程式語言相關 (18)


    小說-離心力 片段 (37)


    知乎 (33)


    異國研究 (0)

    日本 (5)

    俄國 (0)

    印度 (1)

    多文化綜合比較 (5)


    一行文 (11)


    各領域歷史與沿革或說想法發想 (12)

    數學 (11)

    計算機(程式,電路) (3)

    語言 (3)


    讀後感 (1)


    未分類 (154)


    enchnater000ALL
    厭倦一成不變的遊戲了嗎?一起來做屬於你的遊戲吧!http://www.chimakier.com看更多我要大聲說昨天11:21







    googletag.cmd.push(function() googletag.display('div-gpt-ad-1489070677458-0'); );



    (function(window, $)
    var $window = $(window);
    var $document = $(document);
    var $BH_slave = $("#BH-slave");
    var $BH_master = $("#BH-master");
    var $flySalve = $("#flySalve");
    var posY = $flySalve.position().top;
    var fad_style = document.getElementById("flySalve").style;
    var BH_wrapper_width = $('#BH-wrapper').width();
    var BH_topBar_height = $('.TOP-bh').height();
    $(window).on("scroll", function()
    posY = $BH_slave.height() - (fad_style.position === 'fixed' ? 0 : $flySalve.height());

    if ($document.scrollTop() > (posY + $BH_slave.offset().top - BH_topBar_height) && $BH_slave.height() < $BH_master.height())
    fad_style.position = 'fixed';
    fad_style.top = BH_topBar_height + 'px';
    if ($(window).width() < BH_wrapper_width)
    fad_style.left = (BH_wrapper_width - $BH_slave.width() - $document.scrollLeft())+'px';

    else
    fad_style.position = '';

    ).on("resize", function()
    fad_style.left = null;
    );
    )(window, jQuery);
















    face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】





    The name of the picture黑色沙漠手遊伺服器是巴雷諾斯公會缺人名稱是GO歡迎大家查詢到後加入

    This page is only for reference, If you need detailed information, please check here
    The name of the pictureThe name of the picture

    Popular posts from this blog

    【情報】本週珍珠商品重點:煉金時裝 + 艾港勞工宿舍!!

    京昆高速公路

    【攻略】陳戈-謝勒汗智慧的古書 (完成)