diff --git a/BaiduMusicSpider/Spider.py b/BaiduMusicSpider/Spider.py new file mode 100755 index 0000000..962b1af --- /dev/null +++ b/BaiduMusicSpider/Spider.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +import re +import cookielib +import urllib +import urllib2 + +# build cookies jar +cj = cookielib.CookieJar() +opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) +urllib2.install_opener(opener) + +# get cookie +MainUrl = "http://www.baidu.com/" +res = urllib2.urlopen(MainUrl) +for index, cookie in enumerate(cj): + print '[',index,']',cookie + +# get tooken +getTokenUrl = "https://passport.baidu.com/v2/api/?getapi&class=login&tpl=mn&tangram=true" +res = urllib2.urlopen(getTokenUrl) +Html = res.read() +tokenStr = "bdPass.api.params.login_token='(.*?)';" +tokenObj = re.compile(tokenStr,re.DOTALL) +matchObj = tokenObj.findall(Html) +for index, cookie in enumerate(cj): + print '[',index, ']',cookie; +if matchObj: + token = matchObj[0] + print matchObj[0] + +# Login Baidu +LoginUrl = "https://passport.baidu.com/v2/api/?login" +postDict = { + 'charset':"utf-8", + 'token':token, + 'isPhone':"false", + 'index':"0", + 'staticpage':"https://passport.baidu.com/static/passpc-account/html/v3Jump.html", + 'logintype':"basicLogin", + 'tpl':"mn", + 'callback':"parent.bd__pcbs__b0pp2q", + 'username':"250831497@qq.com", + 'password':"220496", + 'mem_pass':"on", + } +postData = urllib.urlencode(postDict); +print postData +req = urllib2.Request(LoginUrl,postData) +req.add_header('Content-Type', "application/x-www-form-urlencoded") +res = urllib2.urlopen(req) + +# handle the baidu music web +Html = res.read() +print Html +for index, cookie in enumerate(cj): + print '[',index, ']',cookie; +urlStr = "encodeURI\('(.*?)'\);" +urlObj = re.compile(urlStr,re.DOTALL) +matchUrl = urlObj.findall(Html) +if matchUrl: + returnUrl = matchUrl[0] +#req = urllib2.Request(returnUrl) +#res = urllib2.urlopen(req) +#print res.read() +songUrl = "http://music.baidu.com/song/120948904/download" +req = urllib2.Request(songUrl) +res = urllib2.urlopen(req) +print res.read() +# TODO: get the download link diff --git a/Hash.cpp b/Hash.cpp new file mode 100644 index 0000000..644fa18 --- /dev/null +++ b/Hash.cpp @@ -0,0 +1,196 @@ +#include "hash.h" +#include "stdafx.h" + +//外部函数 +inline size_t HashTableOffset(size_t f1, size_t f2_f1, size_t t){ + return (f1 * (1 << 12) + f2_f1 * (1 << 6) + t); +} +/* +size_t* ValueTableAddr(size_t* start, HashKeyInfo* pKey){ + return start + pKey->start + pKey->length; +} +*/ +//类方法 +/************************************ Functions for build tracks.(iFlyBuild) ************************************************/ +//此函数用于对于iFlyBuild的情况,从wav到Hash_Table. //Finished. +void THash::BuildInit(){ + //Initialize memory value. + pValueStart = (size_t*)malloc(sizeof(size_t) * HashKeyNum * ValuePerBlock * BlockNum); + if (pValueStart==NULL) + printf("error"); + memset(pValueStart, 0, sizeof(size_t) * HashKeyNum * ValuePerBlock * BlockNum); + //连续内存中,初始化已分配的结尾地址。 + pValueEnd = pValueStart + sizeof(size_t) * ValuePerBlock; + //初始化HashKey表 + key_info = (HashKeyInfo*)malloc(sizeof(HashKeyInfo) * HashKeyNum); + for (int i = 0; i < HashKeyNum; i++){ + key_info[i].next = nullptr; + key_info[i].length = 0; + } +} + +void THash::BuildUnInit(){ + for (int i=0; inext; + free(q); + } + } + free(key_info); + free(pValueStart); +} + +//加歌名,更新歌曲数。 +void THash::AddSongList(const char *filename){ + strcpy_s(song_list[song_num], strlen(filename) + 1, filename); + song_num++; +} + +//往Value的内存块里加数据,更新Key_table. +void THash::InsertHash(size_t f1, size_t f2_f1, size_t t, size_t id, size_t offset){ + //异常处理 + if (id > (1 << ID_BITS) - 1 || offset > (1 << OFFSET_BITS) - 1){ + printf("The id/time offset overflow.\n"); + return; + } + //当前key的地址 + HashKeyInfo *pKey = &key_info[HashTableOffset(f1, f2_f1, t)]; + if (pKey->length%ValuePerBlock==0){ + /*在原来的连续内存中再申请一块*/ + HashKeyInfo * pNode = (HashKeyInfo*)malloc(sizeof(HashKeyInfo)); + /* 内存溢出 */ + if ((pValueEnd - pValueStart) > OverFlowThreshold){ + printf("Memory out.\n"); + return; + } + pNode->start = pValueEnd; + pValueEnd += ValuePerBlock*sizeof(size_t); + pNode->length = 0; + pNode->next = pKey->next; + pKey->next = pNode; + } + size_t* pValue = pKey->next->start + pKey->next->length; + *pValue = (size_t)((id << OFFSET_BITS) + offset); + pKey->next->length++; + pKey->length++; + /* For File Write */ + data_num++; +} + +//将Hash表往文件里刷(不是刷整个内存,这样会在iFlySelect里浪费内存空间) +void THash::Hash2File(const char* filename){ + FILE *fp; + fopen_s(&fp, filename, "wb"); + if (fp == NULL){ + printf("File open WRONG.\n"); + } + //Write SongName + fwrite(&song_num, sizeof(size_t), 1, fp); + printf("共%d首歌\n", song_num); + for (size_t i = 0; istart, sizeof(size_t), p->length, fp); + p = p->next; + } + } + size_t start_place = 0; + for (int i = 0; ilength; + while (length){ + length--; + size_t offset_value = (*(pKey->start + length) << ID_BITS) >> ID_BITS; + if (offset_value < offset) + continue; // 为失效投票,这种情况的投票结果为错的 + vote_table[(*(pKey->start + length)) >> OFFSET_BITS][offset_value - offset]++; + } + return; +} + +size_t THash::VoteResult(size_t &offset){ + size_t result = 0; + short max = -1; + for (size_t i = 0; i < song_num; i++){ + for (size_t j = 0; j < (1< max){ + max = vote_table[i][j]; + result = i; + offset = j; + //if (vote_table[i][j]) + // printf("%d %d %d\n", i, j, vote_table[i][j]); + } + } + return result; +} + +THash::THash(){ + pValueStart = nullptr; + pValueEnd = nullptr; + vote_table = nullptr; + data_num = 0; + song_num = 0; + key_info = nullptr; + song_list = (char **)malloc(MAX_SONG_NUM*sizeof(char*)); + for (int i=0; i + +#define ID_BITS 18 //基本一共可以存26万首歌(如果服务器内存足够大)。 +#define OFFSET_BITS 14 //默认每首歌小于8.7分钟。 +#define MAX_SONG_NUM (2<<18) +#define MAX_SONG_LEN 256 +#define HashKeyNum (1<<20) +#define ValuePerBlock (1<<6) //每一块内存空间大小(64*sizeof(size_t)),用于存哈希桶中的多个value值,可扩容。 +#define BlockNum 4 //Block值,用于动态扩容。 +#define OverFlowThreshold 1<<28 +using namespace std; + +//Hash的key类型,用于iFluBuild +//(f1, f2_f1, t) +struct HashKeyInfo{ + size_t* start; + size_t length; + HashKeyInfo* next; //指针用于扩容 +}; +//Hash的key类型,用于iFluSelect +struct HashKeyTable{ + size_t *start; + size_t length; +}; + +class THash{ +private: +public: + size_t *pValueStart; + size_t *pValueEnd; + short **vote_table; + size_t data_num; + char **song_list; + size_t song_num; + HashKeyInfo *key_info; + HashKeyTable *key_table; + + THash::THash(); + THash::~THash(); + void THash::ReBuildInit(); +/************************************ Functions for build tracks.(iFlyBuild) ************************************************/ + //此函数用于对于iFlyBuild的情况,从wav到Hash_Table. //Finished. + void THash::BuildInit(); + void THash::BuildUnInit(); + //加歌名,更新歌曲数。 //Finished. + void THash::AddSongList(const char *filename); + //往Value的内存块里加数据,更新Key_table. //Finished. + void THash::InsertHash(size_t f1, size_t f2_f1, size_t t, size_t id, size_t offset); + //将Hash表往文件里刷(不是刷整个内存,这样会在iFlySelect里浪费内存空间)//Finished + void THash::Hash2File(const char* filename); + +/************************************ Functions for select tracks.(iFlySelect) ************************************************/ + size_t* THash::GetHash(size_t f1, size_t f2_f1, size_t t); + void THash::File2Hash(const char* filename); + //Functions for vote and save the top voted id to QueryId. + void THash::VoteInit(); + void THash::Vote(size_t f1, size_t f2_f1, size_t t, size_t offset); + size_t THash::VoteResult(size_t &offset); +}; +#endif // _HashFunc_h_ diff --git a/ReadMe.txt b/ReadMe.txt new file mode 100644 index 0000000..a5fdf9b --- /dev/null +++ b/ReadMe.txt @@ -0,0 +1,41 @@ +锘======================================================================== + 鍔ㄦ侀摼鎺ュ簱锛歩FlyBuild 椤圭洰姒傝堪 +======================================================================== + +搴旂敤绋嬪簭鍚戝宸蹭负鎮ㄥ垱寤轰簡姝 iFlyBuild DLL銆 + +鏈枃浠舵瑕佷粙缁嶇粍鎴 iFlyBuild 搴旂敤绋嬪簭鐨勬瘡涓枃浠剁殑鍐呭銆 + + +iFlyBuild.vcxproj + 杩欐槸浣跨敤搴旂敤绋嬪簭鍚戝鐢熸垚鐨 VC++ 椤圭洰鐨勪富椤圭洰鏂囦欢锛屽叾涓寘鍚敓鎴愯鏂囦欢鐨 Visual C++ 鐨勭増鏈俊鎭紝浠ュ強鏈夊叧浣跨敤搴旂敤绋嬪簭鍚戝閫夋嫨鐨勫钩鍙般侀厤缃拰椤圭洰鍔熻兘鐨勪俊鎭 + +iFlyBuild.vcxproj.filters + 杩欐槸浣跨敤鈥滃簲鐢ㄧ▼搴忓悜瀵尖濈敓鎴愮殑 VC++ 椤圭洰绛涢夊櫒鏂囦欢銆傚畠鍖呭惈鏈夊叧椤圭洰鏂囦欢涓庣瓫閫夊櫒涔嬮棿鐨勫叧鑱斾俊鎭傚湪 IDE 涓紝閫氳繃杩欑鍏宠仈锛屽湪鐗瑰畾鑺傜偣涓嬩互鍒嗙粍褰㈠紡鏄剧ず鍏锋湁鐩镐技鎵╁睍鍚嶇殑鏂囦欢銆備緥濡傦紝鈥.cpp鈥濇枃浠朵笌鈥滄簮鏂囦欢鈥濈瓫閫夊櫒鍏宠仈銆 + +iFlyBuild.cpp + 杩欐槸涓 DLL 婧愭枃浠躲 + + 姝 DLL 鍦ㄥ垱寤烘椂涓嶅鍑轰换浣曠鍙枫傚洜姝わ紝鐢熸垚鏃朵笉浼氫骇鐢 .lib 鏂囦欢銆傚鏋滃笇鏈涙椤圭洰鎴愪负鍏朵粬鏌愪釜椤圭洰鐨勯」鐩緷璧栭」锛屽垯闇瑕佹坊鍔犱唬鐮佷互浠 DLL 瀵煎嚭鏌愪簺绗﹀彿锛屼互渚夸骇鐢熶竴涓鍑哄簱锛屾垨鑰咃紝涔熷彲浠ュ湪椤圭洰鈥滃睘鎬ч〉鈥濆璇濇涓殑鈥滈摼鎺ュ櫒鈥濇枃浠跺す涓紝灏嗏滃父瑙勨濆睘鎬ч〉涓婄殑鈥滃拷鐣ヨ緭鍏ュ簱鈥濆睘鎬ц缃负鈥滄槸鈥濄 + +///////////////////////////////////////////////////////////////////////////// +搴旂敤绋嬪簭鍚戝鍒涘缓浜嗕笅鍒楄祫婧愶細 + +iFlyBuild.rc + 杩欐槸绋嬪簭浣跨敤鐨勬墍鏈 Microsoft Windows 璧勬簮鐨勫垪琛ㄣ傚畠鍖呮嫭 RES 瀛愮洰褰曚腑瀛樺偍鐨勫浘鏍囥佷綅鍥惧拰鍏夋爣銆傛鏂囦欢鍙互鐩存帴鍦 Microsoft Visual C++ 涓繘琛岀紪杈戙 + +Resource.h + 杩欐槸鏍囧噯澶存枃浠讹紝鍙敤浜庡畾涔夋柊鐨勮祫婧 ID銆侻icrosoft Visual C++ 灏嗚鍙栧苟鏇存柊姝ゆ枃浠躲 + +///////////////////////////////////////////////////////////////////////////// +鍏朵粬鏍囧噯鏂囦欢: + +StdAfx.h, StdAfx.cpp + 杩欎簺鏂囦欢鐢ㄤ簬鐢熸垚鍚嶄负 iFlyBuild.pch 鐨勯缂栬瘧澶 (PCH) 鏂囦欢鍜屽悕涓 StdAfx.obj 鐨勯缂栬瘧绫诲瀷鏂囦欢銆 + +///////////////////////////////////////////////////////////////////////////// +鍏朵粬娉ㄩ噴: + +搴旂敤绋嬪簭鍚戝浣跨敤鈥淭ODO:鈥濇敞閲婃潵鎸囩ず搴旀坊鍔犳垨鑷畾涔夌殑婧愪唬鐮侀儴鍒嗐 + +///////////////////////////////////////////////////////////////////////////// diff --git a/Resource.h b/Resource.h new file mode 100644 index 0000000..8508b00 --- /dev/null +++ b/Resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by iFlyBuild.rc +// + +#define IDS_APP_TITLE 103 + +// 新对象的下一组默认值 +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/bmp.cpp b/bmp.cpp new file mode 100644 index 0000000..002c8e0 --- /dev/null +++ b/bmp.cpp @@ -0,0 +1,166 @@ +#include "bmp.h" +#include "stdafx.h" + +TBMP::TBMP(char *filename, int w, int h, int mode){ +#ifdef BMP_TEST + char bufferc[4]; + char ch = 255; + unsigned long buffer4; + unsigned short buffer2; + + fopen_s(&fp,filename, "wb"); + if (fp == NULL) printf("!!"); + W = w; + H = h; + MODE = mode%2; + if (W%4!=0) W=(W/4+1)*4; + + int i, j; + bitmap = (char **)malloc(H * sizeof(char *)); + if (bitmap == NULL) printf("00"); + for(i=0; i=0; j--) + fwrite(bitmap[j], 1, W, fp); + fclose(fp); + //realease resources +#endif +} + +int TBMP::setcolor(int grey){ +#ifdef BMP_TEST + if (grey<0 || grey>255) + return 1; + + Grey = grey; + return 0; +#endif +} + +int TBMP::drawpoint(int x, int y){ +#ifdef BMP_TEST + if (!checkborder(x,y)) + return 1; + + if (MODE) + bitmap[H-1-y][x] = Grey; + else + bitmap[y][x] = Grey; + return 0; +#endif +} + +int TBMP::drawline(int x0, int y0, int x1, int y1){ +#ifdef BMP_TEST + if (!checkborder(x0, y0) || !checkborder(x1, y1)) + return 1; + if (x0==x1 && y0==y1) + return drawpoint(x0, y0); + + int xs, ys, xe, ye; + int i, j; + double t; + if (abs(x0-x1) >= abs(y0-y1)){ + if (x0 < x1){ + xs = x0; + ys = y0; + xe = x1; + ye = y1; + } + else{ + xs = x1; + ys = y1; + xe = x0; + ye = y0; + } + t = (double)(ye - ys) / (double)(xe - xs); + for (i=xs; i<=xe; i++){ + j = (int)((i - xs) * t + ys); + drawpoint(i,j); + //bitmap[j][i] = Grey; + } + } + else{ + if (y0 < y1){ + xs = x0; + ys = y0; + xe = x1; + ye = y1; + } + else{ + xs = x1; + ys = y1; + xe = x0; + ye = y0; + } + t = (double)(xe - xs) / (double)(ye - ys); + for (j=ys; j<=ye; j++){ + i = (int)((j-ys) * t + xs); + drawpoint(i,j); + //bitmap[j][i] =Grey; + } + } + return 0; +#endif +} + +int TBMP::drawrect(int x0, int y0, int x1, int y1){ +#ifdef BMP_TEST + return drawline(x0, y0, x0, y1) || drawline(x0, y0, x1, y0) \ + || drawline(x1, y0, x1, y1) || drawline(x0, y1, x1, y1); +#endif +} diff --git a/bmp.h b/bmp.h new file mode 100644 index 0000000..be6ce9c --- /dev/null +++ b/bmp.h @@ -0,0 +1,29 @@ +#ifndef BMP_H +#define BMP_H + +#define BMP_TEST + +#include +#include +#include "stdafx.h" +#define checkborder(x,y) (x>=0 && x=0 && y0 && jpeak[j]) + peak[j] = spectrum[i][j]; + } + for (int j=0; j=0; i--){ + for (int j=0; j= MAX_PAIR_PER_FEATURE) flag = 0; + } + } + return 0; +} + +int TExtractFeature::Feature2PairSearch(THash &hash){ + //hash.VoteInit(); + TBMP tb("pair.bmp", frame_num, FRAME_HEIGHT, 1); + tb.setcolor(0); + int pi, pj; + int count; + int flag; + int index = 0; + for (int i = 0; i= MAX_PAIR_PER_FEATURE) flag = 0; + } + } + return 0; +} + +TExtractFeature::~TExtractFeature(){ + fftw_destroy_plan(fftw_p); + fftw_free(fftw_in); + fftw_free(fftw_out); + + FREE(Gauss_base); + FREE(Hamming); + FREE(threshold); + FREE(peak); + FREE(search); +} + +void TExtractFeature::UnInit(){ + FREE2D(spectrum, frame_num); + FREE2D(feature, frame_num); +} \ No newline at end of file diff --git a/fingerprint.h b/fingerprint.h new file mode 100644 index 0000000..5bd00ea --- /dev/null +++ b/fingerprint.h @@ -0,0 +1,98 @@ +#ifndef FINGERPRINT_H +#define FINGERPRINT_H +/* +#pragma comment(lib, "E:\\LIB\\libfftw3-3.lib") +#pragma comment(lib, "E:\\LIB\\libfftw3f-3.lib") +#pragma comment(lib, "E:\\LIB\\libfftw3l-3.lib") +*/ +#pragma comment(lib, "C:\\fftw\\libfftw3-3.lib") +#pragma comment(lib, "C:\\fftw\\libfftw3f-3.lib") +#pragma comment(lib, "C:\\fftw\\libfftw3l-3.lib") + +#include +#include +#include +#include +#include "wav.h" +#include "Hash.h" +#include "bmp.h" +#include + +#define FRAME_SIZE 512 +#define FRAME_HEIGHT FRAME_SIZE/2 +#define FRAME_HOP 256 +#define LOW_FREQ 20 +#define PAIR_OFFSET 5 +#define PAIR_DX 63 +#define PAIR_DY 31 +#define Gauss_Var 30 +#define PI 3.14159265358979323846 +#define MAX_FEATURE_PER_FRAME 5 +#define MAX_PAIR_PER_FEATURE 32 +#define f2_f1_max 32 +#define MIN_THRESHOLD 0.15 + +#define MALLOC(arr, m, type) {\ + arr = (type *)malloc((m) * sizeof(type));\ + assert(arr != NULL);\ +} + +#define MALLOC2D(arr, m, n, type) {\ + arr = (type **)malloc((m)*sizeof(type*));\ + assert(arr!=NULL);\ + for (int i = 0; i < (m); i++){\ + arr[i] = (type *)malloc((n)*sizeof(type));\ + assert(arr[i]!=NULL);\ + }\ +} + +#define FREE(p) {\ + assert(p != NULL);\ + free(p);\ + p = NULL;\ +} + +#define FREE2D(arr, m) {\ +for (int i = 0; i < (m); i++){\ + FREE(arr[i]);\ + }\ + FREE(arr);\ +}\ + +#define max(a, b) (((a)>(b))?(a):(b)) +#define max3(a,b,c) max(max((a),(b)),(c)) + +class TExtractFeature{ +private: + fftw_complex *fftw_in, *fftw_out; + fftw_plan fftw_p; + float *threshold; + float **spectrum; + float *Gauss; + float *Gauss_base; + float *Hamming; + float *peak; + int **feature; + int frame_num; + int *search; + float decay_factor; + +public: + TExtractFeature(); + ~TExtractFeature(); + + void UnInit(); + void ExtractPair(const char *filename, THash &hash, int offset, float decay, int Id, int mode); + + int Wav2Spectrum(const char *filename, int offset); + int Spectrum2Feature(); + int Feature2PairInsert(THash &hash, int Id); + int Feature2PairSearch(THash &hash); + + void Init(); + int AddSearch(int frame, int freq); + int NotExtremum(int j, float Arr[]); + +}; + +#endif \ No newline at end of file diff --git a/iFlyBuild.cpp b/iFlyBuild.cpp new file mode 100644 index 0000000..314fe4a --- /dev/null +++ b/iFlyBuild.cpp @@ -0,0 +1,78 @@ +// iFlyBuild.cpp : 定义 DLL 应用程序的导出函数。 +// + +#include "stdafx.h" +#include "iFlyBuild.h" +#include "hash.h" +#include "fingerprint.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +// 唯一的应用程序对象 + +CWinApp theApp; + +using namespace std; + +THash myhash; +TExtractFeature fingerprint; +CFileFind finder; + +int Initialize(){ + int nRetCode = 0; + HMODULE hModule = ::GetModuleHandle(NULL); + + if (hModule != NULL) + { + // 初始化 MFC 并在失败时显示错误 + if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) + { + // TODO: 更改错误代码以符合您的需要 + _tprintf(_T("错误: MFC 初始化失败\n")); + nRetCode = 1; + } + else + { + // TODO: 在此处为应用程序的行为编写代码。 + myhash.BuildInit(); + } + } + else + { + // TODO: 更改错误代码以符合您的需要 + _tprintf(_T("错误: GetModuleHandle 失败\n")); + nRetCode = 1; + } + return 0; +} + +int ProcessBuildRes(const char *szResDir, const char *szResPath){ + setlocale(LC_CTYPE, ""); + USES_CONVERSION; + CString szRes = A2T(szResDir); + BOOL bWorking = finder.FindFile(szRes); + int index = 0; + do{ + bWorking = finder.FindNextFile(); + CString FileName = finder.GetFileName(); + if (FileName == L"." || FileName == L"..")continue; + + wprintf(L"The File Name is %s.\n", FileName); + myhash.AddSongList(T2A(FileName)); + fingerprint.ExtractPair(T2A(finder.GetFilePath()), myhash, 0, (float)0.98, index, 0); + fingerprint.UnInit(); + index++; + }while (bWorking); + + myhash.Hash2File(szResPath); + printf("%d.\n", index); + system("pause"); + return 0; +} + +int unInitialize(){ + myhash.BuildUnInit(); + return 0; +} \ No newline at end of file diff --git a/iFlyBuild.h b/iFlyBuild.h new file mode 100644 index 0000000..0710a12 --- /dev/null +++ b/iFlyBuild.h @@ -0,0 +1,41 @@ +#ifndef _IFLY_RES_BUILD_H_ +#define _IFLY_RES_BUILD_H_ + +#include + +#ifdef WIN32 +#define __EXPORT __declspec(dllexport) +#else +#define __EXPORT +#endif /* WIN32 */ + +//+---------------------------------------------------------------------------+ +//+ 初始化 +//+ 对需要的数据结构进行初始化操作 +//+---------------------------------------------------------------------------+ +//+ return - 返回码 +//+---------------------------------------------------------------------------+ +extern "C" __EXPORT int Initialize(); +typedef int(*Proc_Initialize)(); + +//+---------------------------------------------------------------------------+ +//+ 数据打包 +//+ 对给出的歌单进行打包,输出资源文件 +//+---------------------------------------------------------------------------+ +//+ szResDir - 歌曲文件夹输入路径 +//+ szResPath - 资源输出路径 +//+ return - 返回码 +//+---------------------------------------------------------------------------+ +extern "C" __EXPORT int ProcessBuildRes(const char *szResDir, const char *szResPath); +typedef int(*Proc_ProcessBuildRes)(const char *szResDir, const char *szResPath); + +//+---------------------------------------------------------------------------+ +//+ 逆初始化 +//+ 对需要的数据结构进行析构 +//+---------------------------------------------------------------------------+ +//+ return - 返回码 +//+---------------------------------------------------------------------------+ +extern "C" __EXPORT int unInitialize(); +typedef int(*Proc_unInitialize)(); + +#endif//_IFLY_RES_BUILD_H_ \ No newline at end of file diff --git a/iFlySelect.cpp b/iFlySelect.cpp new file mode 100644 index 0000000..8fc71a6 --- /dev/null +++ b/iFlySelect.cpp @@ -0,0 +1,49 @@ +// iFlySelect.cpp : 定义 DLL 应用程序的导出函数。 +// + +#include "stdafx.h" +#include "iFlySelect.h" +#include "Hash.h" +#include "fingerprint.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// 唯一的应用程序对象 +THash myhash; +TExtractFeature fingerprint; + +CWinApp theApp; + +using namespace std; + +int Initialize(const char *szResPath){ + myhash.File2Hash(szResPath); + + myhash.ReBuildInit(); + return 0; +} + +int ProcessSelelct(const char *szAudioPath, std::string &szResultString){ + myhash.VoteInit(); + fingerprint.ExtractPair(szAudioPath, myhash, 0, (float)0.98, 0, 1); + fingerprint.UnInit(); + fingerprint.ExtractPair(szAudioPath, myhash, 64, (float)0.98, 0, 1); + fingerprint.UnInit(); + fingerprint.ExtractPair(szAudioPath, myhash, 128, (float)0.98, 0, 1); + fingerprint.UnInit(); + fingerprint.ExtractPair(szAudioPath, myhash, 192, (float)0.98, 0, 1); + fingerprint.UnInit(); + size_t offset; + size_t result = myhash.VoteResult(offset); + printf("The song is %s, the offset is %f s.\n", myhash.song_list[result], (float)(offset*(float)FRAME_HOP / 8000.0)); + szResultString = myhash.song_list[result]; + + return 0; +} + +int unInitialize(){ + return 0; +} \ No newline at end of file diff --git a/iFlySelect.h b/iFlySelect.h new file mode 100644 index 0000000..d3ab5fd --- /dev/null +++ b/iFlySelect.h @@ -0,0 +1,42 @@ +#ifndef _IFLY_RES_SELECT_H_ +#define _IFLY_RES_SELECT_H_ + +#include + +#ifdef WIN32 +#define __EXPORT __declspec(dllexport) +#else +#define __EXPORT +#endif /* WIN32 */ + +//+---------------------------------------------------------------------------+ +//+ 初始化 +//+ 对需要的数据结构进行初始化操作 +//+---------------------------------------------------------------------------+ +//+ szResPath - 资源输入路径 +//+ return - 返回码 +//+---------------------------------------------------------------------------+ +extern "C" __EXPORT int Initialize(const char *szResPath); +typedef int(*Proc_Initialize)(const char *szResPath); + +//+---------------------------------------------------------------------------+ +//+ 资源检索 +//+ 加载编译好的资源包,对输入的音频进行检索,并输出对应的歌曲名 +//+---------------------------------------------------------------------------+ +//+ szAudioPath - 待检索音频路径 +//+ szResultString - 输出结果,格式:{[忘情水]} +//+ return - 返回码 +//+---------------------------------------------------------------------------+ +extern "C" __EXPORT int ProcessSelelct(const char *szAudioPath, std::string &szResultString); +typedef int(*Proc_ProcessSelelct)(const char *szAudioPath, std::string &szResultString); + +//+---------------------------------------------------------------------------+ +//+ 逆初始化 +//+ 对需要的数据结构进行析构 +//+---------------------------------------------------------------------------+ +//+ return - 返回码 +//+---------------------------------------------------------------------------+ +extern "C" __EXPORT int unInitialize(); +typedef int(*Proc_unInitialize)(); + +#endif//_IFLY_RES_SELECT_H_ diff --git a/stdafx.cpp b/stdafx.cpp new file mode 100644 index 0000000..18ab266 --- /dev/null +++ b/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 只包括标准包含文件的源文件 +// iFlyBuild.pch 将作为预编译头 +// stdafx.obj 将包含预编译类型信息 + +#include "stdafx.h" + +// TODO: 在 STDAFX.H 中 +// 引用任何所需的附加头文件,而不是在此文件中引用 diff --git a/stdafx.h b/stdafx.h new file mode 100644 index 0000000..5df4635 --- /dev/null +++ b/stdafx.h @@ -0,0 +1,36 @@ +// stdafx.h : 标准系统包含文件的包含文件, +// 或是经常使用但不常更改的 +// 特定于项目的包含文件 +// + +#pragma once + +#include "targetver.h" + +#include "hash.h" +#include "wav.h" +#include "fingerprint.h" +#include "bmp.h" + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息 +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的 +#define _AFX_NO_MFC_CONTROLS_IN_DIALOGS // 移除对话框中的 MFC 控件支持 + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // 从 Windows 头文件中排除极少使用的信息 +#endif + +#include +#include // MFC 核心组件和标准组件 +#include // MFC 扩展 +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC 对 Internet Explorer 4 公共控件的支持 +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC 对 Windows 公共控件的支持 +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include +// Windows 头文件: +#include +// TODO: 在此处引用程序需要的其他头文件 diff --git a/targetver.h b/targetver.h new file mode 100644 index 0000000..aadba2f --- /dev/null +++ b/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。 + +// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将 +// WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。 + +#include diff --git a/wav.cpp b/wav.cpp new file mode 100644 index 0000000..4d9e066 --- /dev/null +++ b/wav.cpp @@ -0,0 +1,68 @@ +#include "wav.h" +#include "stdafx.h" + +TWav::TWav(const char *filename){ + fopen_s(&fp, filename, "rb"); + assert(fp != NULL); + + fread(wav_info.riff_id, 1, 4, fp); + wav_info.riff_id[4] = '\0'; + fread(&wav_info.size0, 4, 1, fp); + fread(wav_info.wave_fmt, 1, 8, fp); + wav_info.wave_fmt[8] = '\0'; + fread(&wav_info.size1, 4, 1, fp); + fread(&wav_info.fmttag, 2, 1, fp); + fread(&wav_info.channel, 2, 1, fp); + fread(&wav_info.sample_per_sec, 4, 1, fp); + fread(&wav_info.byte_per_sec, 4, 1, fp); + fread(&wav_info.block_align, 2, 1, fp); + fread(&wav_info.bit_per_sample, 2, 1, fp); + if (wav_info.size1 == 0x10){ + fread(wav_info.data_id, 1, 4, fp); + wav_info.data_id[4] = '\0'; + fread(&wav_info.size2, 4, 1, fp); + } + else{ + fseek(fp, 6, SEEK_CUR); + uint32_t offset; + fread(&offset, 4, 1, fp); + fseek(fp, offset, SEEK_CUR); + fread(wav_info.data_id, 1, 4, fp); + wav_info.data_id[4] = '\0'; + fread(&wav_info.size2, 4, 1, fp); + } + data_offset = wav_info.size0 + 8 - wav_info.size2; + +#ifdef WAV_TEST + printf("=====test file header=====\n"); + printf("riff_id %-8s 文件头标志\"RIFF\"\n", wav_info.riff_id); + printf("size0 %-8d 文件总长-8\n", wav_info.size0); + printf("wave_fmt %-8s 文件头标志\"WAVEfmt \"\n", wav_info.wave_fmt); + printf("size1 %-8s 样例文件/标准文件\n", (wav_info.size1 == 0x12) ? "样例文件" : "标准文件"); + printf("fmttag %-8d \n", wav_info.fmttag); + printf("channel %-8d 声道数\n", wav_info.channel); + printf("sample_per_sec %-8d 采样率\n", wav_info.sample_per_sec); + printf("byte_per_sec %-8d 每秒播放字节数\n", wav_info.byte_per_sec); + printf("block_align %-8d 采样一次占字节数\n", wav_info.block_align); + printf("bit_per_sample %-8d 量化数\n", wav_info.bit_per_sample); + printf("data_id %-8s \"data\"标志\n", wav_info.data_id); + printf("size2 %-8d 采样数据字节数\n", wav_info.size2); + printf("=========================\n"); + printf("播放时长: %d sec\n", wav_info.size2 / wav_info.byte_per_sec); +#endif +} + +TWav::~TWav(){ + fclose(fp); +} + +int16_t TWav::GetSample(){ + int16_t s1; + fread(&s1, 2, 1, fp); + //FIXME check file end + return s1; +} + +void TWav::StartFromOffset(int offset){ + fseek(fp, data_offset+offset, SEEK_SET); +} diff --git a/wav.h b/wav.h new file mode 100644 index 0000000..8b6c44f --- /dev/null +++ b/wav.h @@ -0,0 +1,38 @@ +#ifndef WAV_H +#define WAV_H + +#include +#include +#include +#include "stdafx.h" +//#define WAV_TEST +using namespace std; + +struct Twav_info{ + char riff_id[5]; + uint32_t size0; + char wave_fmt[9]; + uint32_t size1; + uint16_t fmttag; + uint16_t channel; + uint32_t sample_per_sec; + uint32_t byte_per_sec; + uint16_t block_align; + uint16_t bit_per_sample; + char data_id[5]; + uint32_t size2; +}; + +class TWav{ +private: +public: + FILE *fp; + int data_offset; + Twav_info wav_info; + TWav(const char *filename); + ~TWav(); + int16_t GetSample(); + void StartFromOffset(int offset); +}; + +#endif