# HG changeset patch # User Wen X # Date 1287150891 -3600 # Node ID 91301b3d02c5b7831266fdbff3275e5179ce1d51 # Parent f0d2c9b5d3a3bba91c76ba98891fd63fd346d3d0 Example main program. diff -r f0d2c9b5d3a3 -r 91301b3d02c5 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Oct 15 14:54:51 2010 +0100 @@ -0,0 +1,462 @@ +/* + Sample program: analysis of harmonic sinusoid in low-noise monophonic context. + + Syntax: + (executable path) filename ... + + filename: path input wave form audio file, 16-bit PCM + setting: optional algorithmic parameters; search "stricmp" in the source code for a complete list + value: non-default values given to the algorithmic parameters + + Output: + a *.evt file containing RIFF chunks, each starting with id "EVT\0" and hosting a harmonic sinusoid. + + The "EVT\0" chunk body contains a header ("HDR\0") chunk followed by atom ("ATM\0") chunks. + + The "HDR\0" chunk body contains 4 __int32 values: channel index, number of partials, number of + measurement points (frames), and a tag. + + The "ATM\0" chunk body contains an atom structure (see hs.h). + +*/ + +#include +#include "arrayalloc.h" +#include "hs.h" +#include "matrix.h" +#include "quickspec.h" +#include "procedures.h" +#include "vibrato.h" +#include +#include +#include + +//structure hosting wave header data +struct wavehdr +{ + __int16 fmttag; + __int16 channels; + __int32 samplespersec; + __int32 bytespersec; + __int16 blockalign; + __int16 bitspersample; +}; + +//tells if a wave header contains consistent data +bool isvalidwavehdr(wavehdr* hdr) +{ + if (hdr->fmttag!=1) return false; + if (hdr->bitspersample!=8 && hdr->bitspersample!=16) return false; + if (hdr->channels*hdr->bitspersample!=hdr->blockalign*8) return false; + if (hdr->samplespersec*hdr->blockalign!=hdr->bytespersec) return false; + return true; +} + +//structure hosting a waveform audio +struct waveaudio +{ + union + { + wavehdr hdr; + struct + { + __int16 fmttag; + __int16 channels; + __int32 samplespersec; + __int32 bytespersec; + __int16 blockalign; + __int16 bitspersample; + }; + }; + int length; + union + { + unsigned char* data; + unsigned char* data8; + __int16* data16; + }; + waveaudio(){memset(this, 0, sizeof(waveaudio));} + ~waveaudio(){delete[] data;} +}; + +void freewaveaudio(waveaudio* wa) +{ + delete[] wa->data; + memset(wa, 0, sizeof(waveaudio)); +} + +//error messages for reading waveform audio file +enum err_wavefile +{ + err_success, + err_RIFF_hdr, + err_wave_hdr, + err_data_hdr, + err_data_chunk, + err_io +}; + +//reads wave header from file stream +int loadwavehdr(wavehdr* hdr, FILE* fp) +{ + int rc, hdrlen; + char s[5]; + + rc=fread(s, 1, 4, fp); s[4]=0; + if (rc<4) return err_wave_hdr; + if (strcmp(s, "WAVE")) return err_wave_hdr; + + rc=fread(s, 1, 4, fp); s[4]=0; + if (rc<4) return err_wave_hdr; + if (strcmp(s, "fmt ")) return err_wave_hdr; + + rc=fread(&hdrlen, 1, 4, fp); + if (rc<4) return err_wave_hdr; + if (hdrlen<16) return err_wave_hdr; + + rc=fread(hdr, 1, sizeof(wavehdr), fp); + if (rc16) + { + rc=fseek(fp, hdrlen-16, SEEK_CUR); + if (rc!=0) return err_wave_hdr; + } + + return err_success; +} + +//reads waveform audio, including header, from a file stream +int loadwaveaudio(waveaudio* wa, FILE* fp) +{ + int rc, mainlen; + char s[5]; + wavehdr hdr; + + rc=fread(s, 1, 4, fp); s[4]=0; + if (rc<4) return err_RIFF_hdr; + if (strcmp(s, "RIFF")) return err_RIFF_hdr; + + rc=fread(&mainlen, 1, 4, fp); + if (rc<4) return err_RIFF_hdr; + + rc=loadwavehdr(&hdr, fp); + if (rc!=err_success) return rc; + + rc=fread(s, 1, 4, fp); s[4]=0; + if (rc<4) return err_data_hdr; + if (strcmp(s, "data")) return err_data_hdr; + + rc=fread(&mainlen, 1, 4, fp); + if (rc<4) return err_data_hdr; + + if (mainlen<=0) return err_data_hdr; + + unsigned char* data=new unsigned char[mainlen]; + rc=fread(data, 1, mainlen, fp); + if (rchdr=hdr; + wa->length=rc/hdr.blockalign; + delete[] wa->data; + wa->data=data; + + return err_success; +} + +//reads waveform audio, including header, from a file +int loadwavefile(waveaudio* wa, char* filename) +{ + FILE* fp; + if ((fp=fopen(filename, "rb"))==NULL) return err_io; + int result=loadwaveaudio(wa, fp); + fclose(fp); + return result; +} + +//returns new file path with the specific extension replacing the original one +char* ChangeFileExt(char* FileName, char* Ext) +{ + char* oldext=strrchr(FileName, '.'); + int namelen=strlen(FileName)-strlen(oldext); + char* dest=new char[namelen+strlen(Ext)+1]; + memcpy(dest, FileName, namelen); dest[namelen]=0; + strcat(dest, Ext); + return dest; +} + +//ACPower for __int16 data input +double ACPower(__int16* data, int Count) +{ + if (Count<=0) return 0; + double power=0, avg=0, tmp; + for (int i=0; i=autocor[m]) {cont=1; break;} + if (cont==0) + { + if (prd==0 || autocor[m]>autocor[prd]*1.05) prd=m; + } + m++; + } + } + + double pitchbin=0; + if (prd>=minT && prd<=maxT) + { + double mshift; hsr=QIE(&autocor[prd], mshift); pitchbin=wid/(prd+mshift); + } + else{hsr=0;} + delete[] autocor; + return pitchbin; +} + +//main function +int main(int argc, char* argv[]) +{ + //read audio file + if (argc<2){printf("Please specify input wave file."); getch(); return 0;} + printf("Loading wave file %s... ", argv[1]); + waveaudio* wa=new waveaudio; + int waverr=loadwavefile(wa, argv[1]); printf("[%d]\n", waverr); + if (waverr!=err_success){printf("Aborted: error loading wave file."); getch(); return 0;} + if (wa->bitspersample!=16){printf("Aborted: this program accepts 16-bit pcm only."); getch(); return 0;} + + int length=wa->length, sps=wa->samplespersec; + __int16* data16=wa->data16; + if (wa->channels>1) + { + printf("Extracting channel 0... "); + for (int i=1; ichannels]; + printf("[0]\n"); + } + wa->data=0; + delete wa; + + //default settings + int maxhscount=100; + float wid_s=0.02, offstwidratio=0.5; + float dur_s=0.5; + float intv_s=0.05; //duration, in seconds, to scan for peaks + float minf0=55, maxf0=3520; + WindowType wintype=wtHann; + + NMSettings settings; memset(&settings, 0, sizeof(NMSettings)); + settings.hB=3; //spectral truncation half width + settings.maxp=50; //maximal number of partials + settings.maxB=0.001; //stiffness coefficient upper bound + settings.epf=1e-4; //frequency estimation error tolerance for LSE estimation + settings.epf0=1; //input frequency error bound for harmonic grouping + settings.delm=1.1; //frequency error bound for harmonic grouping + settings.delp=1.1; //pitch jump upper bound + + double mina=0.5; + + //user settings through commandline arguments + for (int i=2; i