Google Code Prettify

2014年3月27日 星期四

windows 使用 winmm.lib 錄音(windows sound recording using winmm.lib)


在windows 下有一個 winAPI library 可以實現錄音的功能

API 說明可以參考 MSDN 網站:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd743833(v=vs.85).aspx


這裡主要是介紹如何將電腦麥克風的聲音錄起來,

並存成 wav 檔



1.Audio 結構

在聲音的格式中,定義在 WAVEFORMATEX 這個結構中:


    typedef struct { 

    WORD wFormatTag;       //audio format,這裡使用WAVE_FORMAT_PCM

    WORD nChannels;         //1為單聲道,2為雙聲道

    DWORD nSamplesPerSec;   //每秒採集的聲音sample數量

    DWORD nAvgBytesPerSec;  //每秒傳送byte數量

    WORD nBlockAlign;       //nBlockAlign = (nChannels*wBitsPerSample)/8;

    WORD wBitsPerSample;    //每個sample儲存多少bit的資料,一般為8bit or 16bit

    WORD cbSize;            //額外資訊的大小,通常是non-PCM時,才會用到,這裡設0

} WAVEFORMATEX; 





聲音的採集資料,定義在 WAVEHDR 這個結構中:

typedef struct { 
    LPSTR lpData;              //buffer的資料

    DWORD dwBufferLength;      //buffer的長度

    DWORD dwBytesRecorded;     //buffer的資料大小(bytes)

    DWORD dwUser;              //通常為0

    DWORD dwFlags;             //描述額外的資料

    DWORD dwLoops;             //在播放的時候使用

    struct wavehdr_tag* lpNext;//應該給link list用

    DWORD reserved;            //保留

} WAVEHDR;





2.使用API

  使用windows API錄音 主要利用到下面函式:


  waveInOpen()            //開啟錄音裝置

  waveInPrepareHeader()   //buffer header 準備

  waveInAddBuffer()       //輸入buffer

  waveInStart()           //開始錄音

  waveInStop()            //停止錄音

  waveInUnprepareHeader() //buffer header 清空

  waveInClose()           //關閉錄音裝置



3.code ( 含儲存成wav檔 )

 

#include "stdafx.h"
#include "windows.h"

#pragma comment(lib, "winmm.lib") //windows API library for wave

#define DATASIZE 22050*2*5 //SamplesPerSec * byte per sample * duration time

int _tmain(int argc, _TCHAR* argv[])
{
	HWAVEIN audio_in; 
	WAVEFORMATEX audio_format;  //structure of wave format      
	WAVEHDR audio_header;   

	int log;
	char* soundBuffer[DATASIZE];

	audio_format.wFormatTag=WAVE_FORMAT_PCM;
	audio_format.nChannels=1;
	audio_format.nSamplesPerSec=22050;
	audio_format.wBitsPerSample=16;
	audio_format.cbSize=0;
	audio_format.nBlockAlign  = (audio_format.nChannels * audio_format.wBitsPerSample)/8;
	audio_format.nAvgBytesPerSec = (audio_format.nSamplesPerSec*audio_format.nBlockAlign);

	log = waveInOpen(&audio_in,WAVE_MAPPER,&audio_format,NULL,NULL,NULL);    
        //open input device

	if (log == MMSYSERR_NOERROR) 
		printf("waveInOpen success\n");
	else
		printf("waveInOpen fail\n");	
	                  
	audio_header.dwFlags=0;
	audio_header.dwUser=0;
	audio_header.dwLoops=0;
	audio_header.dwBytesRecorded=0;
	audio_header.lpData = (LPSTR)soundBuffer; 
	audio_header.dwBufferLength = DATASIZE; 
        
        //prepare buffer header
	log = waveInPrepareHeader( audio_in, &audio_header, sizeof(WAVEHDR) );  

	if (log == MMSYSERR_NOERROR) 
		printf("waveInPrepareHeader success\n");
	else
		printf("waveInPrepareHeader fail\n");
        //send buffer to input device
	log = waveInAddBuffer( audio_in, &audio_header, sizeof(WAVEHDR) );      

	if (log == MMSYSERR_NOERROR) 
		printf("waveInAddBuffer success\n");
	else
		printf("waveInAddBuffer fail\n");

	if (! waveInStart(audio_in) )	//start recording										
		printf("recording start for 5 sec...\nenter any char to stop\n"); 
	else 
		printf("recording fail...\n"); 

	getchar();
	if (! waveInStop(audio_in) )	//stop recording										
		printf("recording stop\n"); 
	else 
		printf("recording stop fail\n"); 

        //clean buffer header
	if(waveInUnprepareHeader(audio_in, &audio_header, sizeof(WAVEHDR)))     
		printf("UnPrepare Header fail\n"); 
	else 
		printf("UnPrepare Header success\n"); 

	Sleep(500);

	if (waveInClose(audio_in)==MMSYSERR_NOERROR)
		printf("waveInClose success\n"); 
	else 
		printf("waveInClose fail\n"); 

	//saving as wave file
	MMCKINFO wav_file_header1;
	MMCKINFO wav_file_header2;
	HMMIO wav_file;
	MMRESULT result;
	long wav_log;

        //create wav file
	wav_file = mmioOpen(L"wavfile.wav",NULL,MMIO_CREATE|MMIO_WRITE|MMIO_EXCLUSIVE | MMIO_ALLOCBUF);   
	if(wav_file == NULL)
		 printf("mmioOpen fail\n");

	ZeroMemory(&wav_file_header1, sizeof(MMCKINFO));
	wav_file_header1.fccType=mmioFOURCC('W', 'A', 'V', 'E');

	result = mmioCreateChunk(wav_file ,&wav_file_header1, MMIO_CREATERIFF);  //create RIFF chunk 
	if (result==MMSYSERR_NOERROR)
		printf("mmioCreateChunk: wav_file_header1 %s ok\n",result);
	else
		printf("mmioCreateChunk: wav_file_header1 fail\n");

	
	ZeroMemory(&wav_file_header2, sizeof(MMCKINFO));
	wav_file_header2.ckid=mmioFOURCC('f', 'm', 't', ' ');
	wav_file_header2.cksize=sizeof(WAVEFORMATEX)+audio_format.cbSize;

        //create fmt chunk
	result = mmioCreateChunk(wav_file ,&wav_file_header2, 0);	
	if (result==MMSYSERR_NOERROR)
		printf("mmioCreateChunk wav_file_header2  %s ok\n",result);
	else
		printf("mmioCreateChunk wav_file_header2 fail\n");
        
        //輸入fmt chunk的data
	wav_log = mmioWrite(wav_file ,(char*)&audio_format,sizeof(WAVEFORMATEX)+audio_format.cbSize);   
	if(wav_log==-1)
		printf(  "mmioWrite audio_format fail\n");
	else
		printf(  "mmioWrite write %d bytes\n",wav_log);

        //跳出fmt chunk
        result = mmioAscend(wav_file,&wav_file_header2,0);                   
	if (result==MMSYSERR_NOERROR )
		printf(  "mmioAscend wav_file_header2 %s ok\n",result);
	else
		printf(  "mmioAscend wav_file_header2 %s fail\n",result);

	wav_file_header2.ckid=mmioFOURCC('d', 'a', 't', 'a');

        //create data Chunk
	result = mmioCreateChunk(wav_file ,&wav_file_header2,0);             
	if (result==MMSYSERR_NOERROR)
		printf(  "mmioCreateChunk wav_file_header2 %s ok\n",result);
	else
		printf(  "mmioCreateChunk wav_file_header2 %s fail\n",result);
	printf("audio_header %d BytesRecorded\n",audio_header.dwBytesRecorded);
        
        //輸入audio data 
        wav_log = mmioWrite(wav_file,(char*)audio_header.lpData,DATASIZE);       

	if(wav_log==-1)
		printf( "mmioWrite audio data fail\n");
	else
		printf( "mmioWrite success : write %d bytes\n",wav_log);
	//跳出data chunk 
        result = mmioAscend(wav_file,&wav_file_header2,0);                   
	if (result==MMSYSERR_NOERROR)
		printf(  "mmioAscend wav_file_header2 %s ok\n",result);
	else
		printf(  "mmioAscend wav_file_header2 %s fail\n",result); 
 
        //跳出RIFF chunk
        result = mmioAscend(wav_file,&wav_file_header1,0);                   
	if (result==MMSYSERR_NOERROR)
		printf(  "mmioAscend wav_file_header1 %s ok\n",result);
	else
		printf(  "mmioAscend wav_file_header1 %s fail\n",result);

	result = mmioClose(wav_file,0);	//close the wav file 
	if (result==MMIOERR_CANNOTWRITE){
		printf( "mmioClose fail\n");
	}
	return 0;
}



可以看到儲存下來的wav檔


2014年3月17日 星期一

OpenCV 2.4.8 + mac Xcode 5.1 安裝教學



這次更新成OpenCV 2.4.8,發現跟之前的 OpenCV 2.4.6 + mac Xcode 4.6 安裝教學 

安裝方法幾乎99%一樣,這次使用的Mac air是最近才換的,Xcode首灌就獻給這篇了XD



安裝環境:

MAC OSX 10.9

OpenCV 2.4.8

Xcode 5.1



1.下載opencv: http://opencv.org/

右邊有一個opencv for linux/mac

點下去就會自動下載了


2.安裝homebrew: http://brew.sh/

這是一個很好用的mac安裝許多程式的軟體

只要在終端機上輸入

ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

就會自動下載安裝了

終端機可以在下圖找到






















3.安裝cmake:  http://www.cmake.org/

在終端機輸入

brew install cmake

就會自動下載安裝了


4.安裝Xcode:

直接去App Store 下載安裝,Xcode是免費的

安裝完後 進入Xcode的 preference 裡面的download

下載 command line tool



5.安裝opencv:

將下載回來的opencv壓縮檔解壓縮會跑出資料夾

使用終端機進入解壓縮後的資料夾

比較不熟linux指令的人

可以先用在終端機輸入 =>  ls   ,看現在位置的資料夾

再終端機依序輸入       => cd  資料夾名稱     ,進入壓縮的資料夾中

可以在終端機輸入       => pwd   ,確認當前位置

接著依序輸入

mkdir release

cd release

cmake -G "Unix Makefiles" ..

make

sudo make install



依序完成以上步驟就全都安裝好囉

接下來是新建opencv project



6.建立opencv project:

開啟Xcode 建立專案























建立名稱後 下面type選擇 c++



建立後到build setting -> All

build options -> compiler for c/c++...

選擇LLVM GCC 4.2   我這次在5.1版不需更改就能compiler 成功



到search paths中設定路徑

library search paths 中 輸入 /usr/local/lib

















header search paths 中輸入 /usr/local/include   /usr/local/include/opencv


















7.include lib:

在專案名稱上面按右鍵

選擇add files to.....
























進入後直接按下 /   就會跳出go to the folder 再輸入  /usr/local/lib




























接著把所有的有xxx.2.4.8.dylib檔案都加進去



以上所有環境都設定好囉

可以開始試試看程式了!!!



8.final test:


貼上以下code

//
//  main.cpp
//  tutorial_opencv2.4.8
//
//  Created by Vince on 2014/3/17.
//  Copyright (c) 2014年 vince. All rights reserved.
//


#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"


using namespace cv;
using namespace std;

int main(int argc, char *argv[])
{
    cv::Mat src;
    
    src=cv::imread("/Users/Vince/Documents/MyPictures/apple logo.jpeg", -1);
    
    //上面的路徑為圖片路徑
    
    cv::imshow("show image",src);  //這邊會show圖出來
    
    cv::waitKey(0);
    
    return 0;
}


如果看得到圖片就大功告成囉~~





    

2014年3月16日 星期日

Sublime text Package for Arduino


最近發現一個Arduino的Package  Stino

它是一個Open Source的專案,

可以直接透過Sublime text 編譯Arduino程式,

最讓我覺得實用的功能是他有Key word Highlight Auto pop

這樣就不用每次打code時還要把完整的keyword打完

效率增加不少喔~


1.準備工具

Sublime Text 2 or 3

Arduino主程式



2.安裝套件

有兩種安裝方式,Console下指令安裝下載檔案安裝

//------------------------------------------------------------------------------------------------------------

Console下指令安裝:

開啓Sublime text -> view ->show console




依自己安裝的版本貼上

Subtext text2:

import urllib2,os,hashlib; h = '7183a2d3e96f11eeadd761d777e62404' + 'e330c659d4bb41d3bdf022e94cab3cd0'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by) if dh == h else None; print('Error validating download (got %s instead of %s), please try manual install' % (dh, h) if dh != h else 'Please restart Sublime Text to finish installation')

Sublime text3:

import urllib.request,os,hashlib; h = '7183a2d3e96f11eeadd761d777e62404' + 'e330c659d4bb41d3bdf022e94cab3cd0'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)


完成後將Sublime text關掉後重開

重新開啟後,Preferences->Package Control



輸入 Package Control: Install Package


接著輸入  Arduino-like IDE 安裝套件

//-----------------------------------------------------------------------------------------------------------------

下載檔案安裝:




Preferences -> Browse packages



將剛剛下載的 Stino-master 解壓縮到資料夾中就完成囉!




3.設定Arduino編譯器

開啟Arduino標頭列



這時候會發現標頭列已經有Arduino的選項出現



Arduino->Preferences->Select Arduino Application Folder




找到你的Arduino.app的安裝路徑



看到這個就代表安裝編譯器設定完成了



4.開始編寫Arduino code

Arduino -> New Sketch



可以看到keyword 會auto pop



打完就可以編譯和燒錄板子囉!!



2014年3月7日 星期五

Sublime Text for Verilog Plugin in MAC



1.到官網下載verilog package

http://sublimetextinfo.sourceforge.net/pages/Verilog.html



2.找到sublime text 的安裝目錄


進入資料夾 Contents  —> MacOS —> Packages

將下載的 Verilog.sublime-package 放入資料夾內重新開啓sublime text 就可以了




3.結果測試




2014年3月4日 星期二

Altera DDR2 Controller Tutorial



1.使用Altera DDR2 IP








2.IP訊號定義

local_addr[23:0]
input
DDR2儲存位置,每個記憶體位置儲存32bit資料
local_be[15:0]
input
寫入資料用,每筆資料全部寫入下16'hFFFF
local_burstbegin
input
For write req and read req,每筆資料拉high做讀或寫
local_read_req
input
讀取資料訊號
local_write_req
input
寫入資料訊號
local_size[]
input
Size = 2 for DDR2
local_wdata[]
input
寫入資料,這裡為128bit,寫入4個記憶體位置,每32bit一筆
local_rdata[]
output
讀出資料,這裡為128bit,讀出4個記憶體位置,每32bit一筆
local_init_done
output
DDR2初始化完成訊號
local_rdata_valid
output
可以開始接收讀出的資料
local_ready
output
Pull highburstbegin才有效




3.IP訊號




Write:

ready pull high時,burstbeginpull high一次,寫入2 (local_size) 筆資料,

記憶體位置則增加8


Read:

ready pull high時,burstbeginpull high,請求讀2 (local_size) 筆資料,

記憶體位置則增加8read_reqpull high到請求讀出的資料位置最末筆。

local_valid訊號pull high時,開始讀出資料,每筆資料有4個記憶體位置,

pull low時讀取結束


2014年3月3日 星期一

Altera ModelSim Tutorial



1.下載檔案


2.建立ModelSim 專案






















 



















:路徑和檔名最好以英文命名才不會發生錯誤


3.增加編譯好的 .V(包括testbench的檔案)
 
 













選擇Copy to project directory 後按OK


4.編譯檔案

























選擇Compile All,檔案編譯完成後status會從" ? " 變成 ""




5.選擇模擬檔案
選擇Start Simulation

























在路徑work裡選擇testbench




















6.執行結果
view 勾選 Objects Wave























將要顯示的input output Pin拖曳到 wave 視窗























選擇模擬時間,按下Run(F9)開始模擬,
要清除重新模擬按下Restart清除重來




















Mags 可以按右鍵Radix選擇顯示的方式