# HG changeset patch # User Chris Cannam # Date 1383650255 0 # Node ID e3a4831f9c64f2983ee63a1f6b4dfba082c6b786 # Parent f45af8d8091eb73a17ba4004c46350fcbeccf4f3# Parent 66ef06a6d591daae234799aa7f3f2f3788daa2d4 Merge from the default branch diff -r 66ef06a6d591 -r e3a4831f9c64 .hgsubstate --- a/.hgsubstate Tue Nov 05 11:14:16 2013 +0000 +++ b/.hgsubstate Tue Nov 05 11:17:35 2013 +0000 @@ -1,4 +1,4 @@ 236814e07bd07473958c1ff89103124536a0c3c8 dataquay 3fc0df28953377c96e501f41db6fb80d29d6aa4a svapp e50a8fee67529803a1512d1ddd83eb6a76d853c4 svcore -d8bd193ad17dfac2e50090969a217461441ea70c svgui +26c5f7fd4807211cc18b3e8e68b67f43e962203c svgui diff -r 66ef06a6d591 -r e3a4831f9c64 main/IMAFencoder.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/IMAFencoder.c Tue Nov 05 11:17:35 2013 +0000 @@ -0,0 +1,2980 @@ +//***********************************************************// +// Interactive Music Audio Format (IMAF) ENCODER // +// Version 2.0 // +// // +// Eugenio Oñate Hospital // +// Jesús Corral García & Costantino Taglialatela // +// // +// Copyright (c) 2013 Centre for Digital Music (C4DM) // +// Queen Mary University of London. All rights reserved. // +//***********************************************************// +// main.c // +//***********************************************************// + +//File input/output +#include +//Standard library: numeric conversion, memory allocation... +#include +//Operations with strings +#include +//Get the creation time: clock +#include +#include "IMAFencoder.h" +//Qt libraries +#include +#include +#include + + +/*Prototype*/ +void filetypebx(FileTypeBox *ftyp); +int mdatbox(MediaDataBox *mdat, int, FILE *imf, FILE *song, FILE *text, int, int, u32); +void moovheaderbox(MovieBox *moov, int, int, int, int, int, int, int); +int trackstructure(MovieBox *moov, int, int, int, int,const char *name); +int samplecontainer(MovieBox *moov, int, int, const char *name); +int sampledescription(MovieBox *moov, int); +int presetcontainer(MovieBox *moov, int, int *vol_values, int type, int fade_in); +int rulescontainer(MovieBox *moov, int SelRuleType, int SelRule_PAR1, int SelRule_PAR2, + int MixRuleType, int MixRule_PAR1, int MixRule_PAR2, int MixRule_PAR3, int MixRule_PAR4); +void writemoovbox(MovieBox moov, int numtrack,int totaltracks, FILE *imf, FILE *text, bool HasTextFile); +int readTrack(MovieBox *moov, int,const char *name); + +// Timed Text Functions +int trackstructure_text (MovieBox *moov, int numtrack, int clock, int durationTrack, int sizemdat,const char *textfile,FILE *text,int totaltracks); +int samplecontainer_text(MovieBox *moov, int numtrack, int sizemdat, const char *textfiles,int totaltracks); +int aux (FILE *text,int num,int num1,int num2,int num3,int *sal); +int getTextSize (FILE *text); +// Group and Preset functions +int groupcontainer(MovieBox *moov, int *group_tracks, int grp_vol, QString grp_name, + QString grp_description, int totaltracks); +void writepresets(MovieBox moov, int numtrack,int totaltracks, FILE *imf); // NOT YET USED + +// MetaData and JPEG Image functions +int metacontainer (MetaBox *meta); +u32 getImageSize(const char *imag); +void insertImage (MetaBox *meta, FILE **imf, u32 imagesize, const char *imagedir); +void writemetabox(MetaBox meta, FILE *imf); + +int bytereverse(int num); +int bytereverse16(int num); +int size_phrase[1000];//the total number of bytes in a phrase including modifiers +int phrases;//the number of phrases in the whole text + + +// Qt Widget for the "Exit Window" +class ExitWindow : public QWidget +{ + public: + ExitWindow(); + private: + QMessageBox *file_created; +}; + +ExitWindow::ExitWindow() +{ + file_created = new QMessageBox(); + file_created->setFixedSize(400,200); // doesn't seem to work + file_created->setWindowTitle("IM AF Encoder"); + file_created->setText("IM AF file successfully created!"); + file_created->show(); +} + +int mainIMAFencoder (int totaltracks, QString files_path[maxtracks],QString outimaf, + QString picturefile, QString textfile, int vol_values[maxtracks], bool HasImageFile, + bool HasTextFile, int SelRuleType, int SelRule_PAR1, int SelRule_PAR2, + int MixRuleType, int MixRule_PAR1, int MixRule_PAR2, int MixRule_PAR3, int MixRule_PAR4, + int group_tracks[maxtracks], int group_volume, QString group_name, QString group_description, + int pres_type, int fade_in) +{ + //Variables + FileTypeBox ftyp; + MediaDataBox mdat; + MovieBox moov; + MetaBox meta; + + //Media Data Box - Contains the audio + FILE *song; //MP3 + u32 sizeTRAK = 0; + int numtr; + //Output File + FILE *imf; //IMA + int numtrack, sizemdat, durationTrack; + //Image + u32 imagesize; + QTextStream out (stdout); + //Timed-Text + FILE *text; + int sizetext; + const char *c_str1[8];//change this value to support more than 8 audio tracks + const char *c_str2; + + //Groups, Presets, Rules and Metadata boxes sizes + u32 sizeGRCO, sizePRCO, sizeRUCO, sizeMETA; + + /* Obtain current time as seconds elapsed since the Epoch. */ + time_t clock = time(NULL); + + + //INPUT: Image + if (HasImageFile){ + c_str2= picturefile.toStdString().c_str(); //convert QString to const char + imagesize = getImageSize(c_str2);//calculate the size of the jpeg + } else { //if there is no image, the size is 0 + imagesize = 0; + } + + //INPUT: Timed-Text + if (HasTextFile){ + c_str2= textfile.toStdString().c_str(); //convert Qstring to const char + text = fopen(c_str2, "rb"); + sizetext= getTextSize (text); //calculate the size of the text + } + else{ + sizetext = 0; + } + //Create OUTPUT file (.ima) + imf = fopen (outimaf.toStdString().c_str(),"wb"); + + //Define the File Type Box + filetypebx(&ftyp); + fwrite(&ftyp, sizeof(FileTypeBox),1, imf); + //AUDIO + //Put the tracks in Media Data Box + for (numtr=0; numtr enter sizeGRCO instead of 0 + + //Writes the movie box into the file + writemoovbox(moov, numtrack, totaltracks, imf, text, HasTextFile); + + //Writes the meta box into the IMAF file + if (HasImageFile){ + writemetabox(meta,imf); + } + + //Close Files and show exit dialog window + fclose(imf); + fclose (text); + ExitWindow *window = new ExitWindow(); +} + + + +void filetypebx(FileTypeBox *ftyp){ + int swap; + + swap = bytereverse(24);// 24 is the size of the box "ftyp" + ftyp->size = swap; + swap = bytereverse('ftyp'); + ftyp->type = swap; + swap = bytereverse('im02'); // Conformance point 3 (see ISO/IEC 23000-12:2010/FDAM 1:2011(E)) + ftyp->major_brand = swap; + ftyp->minor_version = 0; + swap = bytereverse('im02'); // Conformance point 3 (see ISO/IEC 23000-12:2010/FDAM 1:2011(E)) + ftyp->compatible_brands[0] = swap; + swap = bytereverse('isom'); + ftyp->compatible_brands[1] = swap; +} + +int mdatbox(MediaDataBox *mdat, int totaltracks, FILE *imf, FILE *song, FILE *text, int numtr, int sizetext, u32 imagesize){ + + int d=0, cnt=0, j, find = 0, sizestring = 0, i = 0,cnt2=0,highlight_end_time=0; + int dat = 0, dat1 = 0, dat2 = 0, dat3 = 0,k=0; + u32 size = 0, swap, sizeMDAT = 0; + unsigned char c1=0,c2=0,numwords=0,initposition[3000],endposition[3000]; + + //Positionate the pointer at the end of the file to know the size of it + fseek(song, 0, SEEK_END); + size = ftell(song); + //Positionate the pointer at first + fseek(song, 0, SEEK_SET); + + initposition[0]=0; // this array saves the position of the first letter of a word in a phrase + phrases=0;// this variable saves the number of phrases in the whole text + + //Find the header of the first frame (the beginning), when find it d=1 and jump out the loop. + // The header is 32 bytes. We find in groups of 8 bytes + // Contemplate all possible options of headers + while (d == 0) { + find = 0; + fread(&dat, sizeof(unsigned char), 1, song); + cnt++; + + if (dat == 0xFF) { + cnt++; // cnt : stores the position of the pointer. + fread(&dat1, sizeof(unsigned char), 1, song); + cnt++; + fread(&dat2, sizeof(unsigned char), 1, song); + cnt++; + fread(&dat3, sizeof(unsigned char), 1, song); + if (dat1 == 0xFB && dat2 == 146 && dat3 == 64 ) { + find = 1; // find: if the header is found + d=1; // d: jump out the loop + } + if (dat1 == 0xFB && dat2 == 146 && dat3 == 96 ) { + d=1; + find = 1; + } + if (dat1 == 0xFB && dat2 == 144 && dat3 == 64 ) { + find = 1; + d=1; + } + if (dat1 == 0xFB && dat2 == 144 && dat3 == 96 ) { + find = 1; + d=1; + } + if (dat1 == 0xFB && dat2 == 146 && dat3 == 100 ) { + d=1; + find = 1; + } + if (dat1 == 0xFB && dat2 == 144 && dat3 == 100 ) { + find = 1; + d=1; + } + if (dat1 == 0xFA && dat2 == 146 && dat3 == 64 ) { + find = 1; + d=1; + } + if (dat1 == 0xFA && dat2 == 146 && dat3 == 96 ) { + d=1; + find = 1; + } + if (dat1 == 0xFA && dat2 == 144 && dat3 == 64 ) { + find = 1; + d=1; + } + if (dat1 == 0xFA && dat2 == 144 && dat3 == 96 ) { + find = 1; + d=1; + } + if (dat1 == 0xFA && dat2 == 146 && dat3 == 100 ) { + d=1; + find = 1; + } + if (dat1 == 0xFA && dat2 == 144 && dat3 == 100 ) { + find = 1; + d=1; + } + if (find == 0) { + fseek(song, -3, SEEK_CUR); // if 3 last bytes in the header are not correct + cnt = cnt - 3; + } + } // close if + if (cnt == size) { //if we have readen all the bytes in the audio file + d = 1; + } + }//close while + size = size - (cnt - 4); // Calculate the size of the samples. size = pos. end of file - pos. first header. + if (numtr == 0) { //if it is the first audio track the code writes the mdat size + sizeMDAT = size*totaltracks + 8 + sizetext + imagesize; // size of the whole media box -> INCLUDING IMAGE and TEXT SIZE.The text size does not include modifiers + swap = bytereverse(sizeMDAT); + fwrite(&swap, sizeof(u32), 1, imf); + swap = bytereverse('mdat'); + mdat->type = swap; + fwrite(&mdat->type, sizeof(u32), 1, imf); + } + fseek(song, cnt - 4, SEEK_SET); + for (j=0; jdata, sizeof(char), 1, song); + fwrite(&mdat->data, sizeof(char), 1, imf); + } + + // copy the text in the 3gp to the ima and add the text modifiers + if (sizetext !=0){ + cnt=0;// the total number of bytes of the whole text including modifiers + fseek(text,0,SEEK_CUR); + sizestring=0;//number of bytes of a phrase (without modifiers) + initposition[0]=0;// this array saves the initial position of a word + if(numtr==totaltracks-1){ // writes the text after the samples of all the audio tracks + j=0;cnt=0; + while(jdata,sizeof(char),1,text); + fwrite(&mdat->data,sizeof(char),1,imf); + j++; + cnt=cnt+1; + cnt2=cnt2+1; + if(mdat->data==0x20){ //a blank space separates two words. 0x20 = blank space + + numwords++; + endposition[k]=i; + initposition[k+1]=i+1; + k++; + } + + + } //close for + endposition[k]=sizestring-1;//saves the last position of the last word in a phrase + numwords++; + + + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//hclr size + fwrite(&mdat->data,sizeof(char),1,imf);//hclr size + fwrite(&mdat->data,sizeof(char),1,imf);//hclr size + mdat->data=0x0C; + fwrite(&mdat->data,sizeof(char),1,imf); //hclr size + fwrite("h",sizeof(char),1,imf); + fwrite("c",sizeof(char),1,imf); + fwrite("l",sizeof(char),1,imf); + fwrite("r",sizeof(char),1,imf); + mdat->data=0xFF; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight color rgba + mdat->data=0x62; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight color rgba + mdat->data=0x04; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight color rgba + mdat->data=0xFF; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight color rgba + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf); //krok size + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//krok size + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//krok size + mdat->data=14+(8*numwords); + fwrite(&mdat->data,sizeof(char),1,imf); //krok size + fwrite("k",sizeof(char),1,imf); + fwrite("r",sizeof(char),1,imf); + fwrite("o",sizeof(char),1,imf); + fwrite("k",sizeof(char),1,imf); + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-start-time + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-start-time + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-start-time + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-start-time + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//entry-count + mdat->data=numwords; + fwrite(&mdat->data,sizeof(char),1,imf);//entry-count + + for(i=0;idata=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-end-time + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-end-time + + + if(i==numwords-1){ //if it is the last word in a phrase we put this value + mdat->data=0xFF; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-end-time + mdat->data=0xFF; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-end-time + + } + + else{ //if it is not the last word in a phrase + + highlight_end_time = (i+1)*(11/numwords);//change the value '11' in order to increase o decrease the speed of highlight + mdat->data= highlight_end_time; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-end-time + mdat->data=0xFF; + fwrite(&mdat->data,sizeof(char),1,imf);//highlight-end-time + + + } + + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//startcharoffset + mdat->data=initposition[i]; + fwrite(&mdat->data,sizeof(char),1,imf);//startcharoffset + mdat->data=0x00; + fwrite(&mdat->data,sizeof(char),1,imf);//endcharoffset + mdat->data=endposition[i]+1; + fwrite(&mdat->data,sizeof(char),1,imf);//endcharoffset + + }//close for + + cnt=cnt+26+(numwords*8);//cnt is the number of bytes of the whole text including modifiers + cnt2=cnt2+26+(numwords*8); //cnt2 is the number of bytes of a phrase including the modifiers + + size_phrase[phrases-1]=cnt2 ; + + } //close while + + sizeMDAT = size*totaltracks + 8 + cnt + imagesize; // size value must include image and text sizes + swap = bytereverse(sizeMDAT); + fseek(imf,-(sizeMDAT-imagesize),SEEK_CUR); //overwrittes sizeMDAT with the total size (Image is yet to be written in the file at this point) + fwrite(&swap, sizeof(u32), 1, imf); + fseek(imf,(sizeMDAT-imagesize)-4,SEEK_CUR); // (Image is yet to be written in the file at this point) + } // close if (numtr==totaltracks-1) +}//close if sizetext + fclose(song); + + return size; +} + +int samplecontainer(MovieBox *moov, int numtrack, int sizemdat, const char *name){ + + u32 sizeSTSD, sizeSTSZ, swap, num_samples, dat=0; + u32 sizetime, sizeSTTS; //Time to Sample Box + u32 sizeSTSC = 28; //Sample to Chunck + u32 sizeSTCO = 20; //Chunck offset + u32 sizeSTBL; //Sample Table Box // + + //Sample Description Box// + sizeSTSD = sampledescription(moov, numtrack); + + //Sample size box// + swap = bytereverse('stsz'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.version = 0; + //Read Track: Frame size and Decoder Times + num_samples = readTrack(moov, numtrack, name); + sizeSTSZ = num_samples*4 + 20; + swap = bytereverse(sizeSTSZ); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.size = swap; + + //Time To Sample Box// + sizetime = bytereverse(moov->TrackBox[numtrack].MediaBox.MediaInformationBox. + SampleTableBox.TimeToSampleBox.entry_count); + sizeSTTS = 16 + sizetime*4*2; + swap = bytereverse(sizeSTTS); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.size = swap; + swap = bytereverse('stts'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.version = 0; + + //Sample To Chunk// + swap = bytereverse(sizeSTSC); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.size = swap; + swap = bytereverse('stsc'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.version = 0; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.entry_count = swap; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.first_chunk = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.samples_per_chunk = moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox.sample_count; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.sample_description_index = swap; + + //Chunk Offset Box// + swap = bytereverse(sizeSTCO); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.size = swap; + swap = bytereverse('stco'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.version = 0; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.entry_count = swap; + dat = 32 + sizemdat*numtrack; + swap = bytereverse(dat); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.chunk_offset[numtrack] = swap; + + //Sample Table Box // + sizeSTBL = 8 + sizeSTSD + sizeSTSZ + sizeSTSC + sizeSTCO + sizeSTTS; + swap = bytereverse(sizeSTBL); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.size = swap; + swap = bytereverse('stbl'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.type =swap; + + return sizeSTBL; +} + +int sampledescription(MovieBox *moov, int numtrack){ + + u32 swap, sizeESD = 35; + + u32 sizeMP4a; //Audio Sample Entry// + u32 sizeSTSD; //Sample description box // + + + swap = bytereverse(sizeESD); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.size = swap; + swap = bytereverse('esds'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.version = 0; + + //ES Descriptor// + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor.tag = 3; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor.length = 21; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor.ES_ID = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor.mix = 0; + + //Decoder config descriptor// + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + DecoderConfigDescriptor.tag = 4; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + DecoderConfigDescriptor.length = 13; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + DecoderConfigDescriptor.objectProfileInd = 0x6B; + swap = bytereverse(0x150036B0); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + DecoderConfigDescriptor.mix = swap; + swap = bytereverse(128); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + DecoderConfigDescriptor.maxBitRate = swap; + swap = bytereverse(128); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + DecoderConfigDescriptor.avgBitrate = swap; + + //SLConfig Descriptor// + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + SLConfigDescriptor.tag = 6; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + SLConfigDescriptor.length = 1; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.ESbox.ES_Descriptor. + SLConfigDescriptor.predifined = 2; + + //Audio Sample Entry// + sizeMP4a = 36 + sizeESD; + swap = bytereverse(sizeMP4a); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.size = swap; + swap = bytereverse('mp4a'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.type =swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved[0] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved[1] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved[2] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved[3] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved[4] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved[5] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.data_reference_index = bytereverse16(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved2[0] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved2[1] = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.channelcount = 512; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.samplesize = 4096; // 16 bits + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.reserved3 = 0; + swap = 44100 << 16; + swap = bytereverse(swap); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.AudioSampleEntry.samplerate = swap; + + //Sample description box // + sizeSTSD = 16 + sizeMP4a; + swap = bytereverse(sizeSTSD); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.size = swap; + swap = bytereverse('stsd'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.version = 0; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.entry_count = swap; + + return sizeSTSD; +} + +int readTrack (MovieBox *moov, int numtrack,const char *name){ + + int t=0,k=1, l =0; + + FILE *song; + int d=0, cnt = 0, i=0, j=0, cnt2 = 0, find = 0, swap, num_entr = 0; + int dat = 0, dat1 = 0, dat2 = 0, dat3 = 0, num_frame = 0, end =0, pos = 0; + u32 size[9000]; + + //Open the audio file with the name introduced by the user + song = fopen (name,"rb"); + if (song == NULL) { + printf("Error opening input file\n"); + system("pause"); + exit(1); + } + //Calculate the size of the track + fseek(song, 0, SEEK_END); + end = ftell(song); + fseek(song, 0, SEEK_SET); + d=0, i=0; + //Search for each frame one by one, and extratcs the information + while (d == 0) { + find = 0; + fread(&dat, sizeof(unsigned char), 1, song); + cnt++; + + if (dat == 0xFF) { + cnt++; + fread(&dat1, sizeof(unsigned char), 1, song); + cnt++; + fread(&dat2, sizeof(unsigned char), 1, song); + cnt++; + fread(&dat3, sizeof(unsigned char), 1, song); + if (dat1 == 0xFB && dat2 == 146 && dat3 == 64 ) { + pos = cnt - 4; //Pos of the beginning of the frame + size[num_frame] = pos - cnt2; //Size of one frame + cnt2 = pos; //Pos of the next frame + find = 1; + num_frame ++; //Number of frames + } + if (dat1 == 0xFB && dat2 == 146 && dat3 == 96 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFB && dat2 == 144 && dat3 == 64 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFB && dat2 == 144 && dat3 == 96 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFB && dat2 == 146 && dat3 == 100 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFB && dat2 == 144 && dat3 == 100 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFA && dat2 == 146 && dat3 == 64 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFA && dat2 == 146 && dat3 == 96 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFA && dat2 == 144 && dat3 == 64 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFA && dat2 == 144 && dat3 == 96 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFA && dat2 == 146 && dat3 == 100 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (dat1 == 0xFA && dat2 == 144 && dat3 == 100 ) { + pos = cnt - 4; + size[num_frame] = pos - cnt2; + cnt2 = pos; + find = 1; + num_frame ++; + } + if (find == 0) { //In case it does not find the header. + //It keeps reading next data without jump any position + fseek(song, -3, SEEK_CUR); + cnt = cnt - 3; + } + } + + if (cnt == end) { + pos = cnt; + size[num_frame] = pos - cnt2; + d = 1; + } + } + + //Save Samples size// + swap = bytereverse(num_frame); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.sample_count = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.sample_size = 0; + + for (i=0; i< num_frame; i++) { + swap = bytereverse(size[i+1]); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.entry_size[i] = swap; + } + + //Save Decoding Times// + //Writes manually the duration of each frame. + //Follows the following structure: + // 7 frames of 26 ms + // 1 frame of 27 ms + // ... + // And each 13 rows it writes + // 8 frames of 26 ms + // 1 frame of 27 ms + //It is done for adjusting the different durations of each frame. + // as they vary between 26.125 ms and 26.075 ms + + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_count[0] = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_delta[0] =0; + // int t=0,k=1, l =0; + num_entr = 1; + j = 0; + for (i = 1; i< num_frame; i++) { + if (j == 8 && l == 0) { + swap = bytereverse(7); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_count[num_entr] = swap; + swap = bytereverse(26); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_delta[num_entr] =swap; + num_entr ++; + + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_count[num_entr] = swap; + swap = bytereverse(27); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_delta[num_entr] =swap; + num_entr++; + j=0; + dat = i; + if (k == 6 && t == 0) { + l = 1; + t = 1; + k = 1; + } + if (k == 6 && t ==1) { + l = 1; + k = 1; + } + k++; + } + + if (j == 9 && l == 1) { + + swap = bytereverse(8); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_count[num_entr] = swap; + swap = bytereverse(26); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_delta[num_entr] =swap; + num_entr ++; + + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_count[num_entr] = swap; + swap = bytereverse(27); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_delta[num_entr] =swap; + num_entr++; + j=0; + dat = i; + l = 0; + } + j++; + } + + dat = num_frame - dat; + + swap = bytereverse(dat); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_count[num_entr] = swap; + swap = bytereverse(26); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.sample_delta[num_entr] =swap; + num_entr++; + swap = bytereverse(num_entr); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.entry_count = swap; + + fclose(song); + return num_frame; + +} + +int trackstructure (MovieBox *moov, int numtrack, int clock, + int durationTrack, int sizemdat,const char *name){ + int swap; + + int sizeSTBL; //Sample Table Box + u32 sizeURL; //Data Entry Url Box + u32 sizeDREF; //Data Reference + u32 sizeSMHD; //Sound Header Box + u32 sizeDINF; //Data information Box + u32 sizeMINF; //Media Information Box// + u32 sizeHDLR; //Handler Box// + u32 sizeMDHD; //Media Header Box// + u32 sizeMDIA; //Media Box// + u32 sizeTKHD; //Track Header// + u32 sizeTRAK; //Track container + + //Sample Table Box + sizeSTBL = 0; + sizeSTBL = samplecontainer(moov, numtrack,sizemdat, name); + + //Data Entry Url Box + sizeURL = 12; + swap = bytereverse(sizeURL); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.DataEntryUrlBox.size = swap; + swap = bytereverse('url '); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.DataEntryUrlBox.type = swap; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.DataEntryUrlBox.flags = swap; // =1 Track in same file as movie atom. + + //Data Reference + sizeDREF = sizeURL+ 16; + swap = bytereverse(sizeDREF); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.size = swap; + swap = bytereverse('dref'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.flags = 0; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.entry_count = swap; + + //Data information Box// + sizeDINF = sizeDREF + 8; + swap = bytereverse(sizeDINF); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.size = swap; + swap = bytereverse('dinf'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.type = swap; + + //Sound Header Box // + sizeSMHD = 16; + swap = bytereverse(sizeSMHD); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox.size = swap; + swap = bytereverse('smhd'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox.version = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox.balance = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox.reserved = 0; + + //Media Information Box// + sizeMINF = sizeDINF + sizeSMHD + sizeSTBL + 8; + swap = bytereverse(sizeMINF); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.size = swap; + swap = bytereverse('minf'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.type = swap; + + //Handler Box// + sizeHDLR = 37; + swap = bytereverse(sizeHDLR); + moov->TrackBox[numtrack].MediaBox.HandlerBox.size = swap; + swap = bytereverse('hdlr'); + moov->TrackBox[numtrack].MediaBox.HandlerBox.type = swap; + moov->TrackBox[numtrack].MediaBox.HandlerBox.version = 0; + moov->TrackBox[numtrack].MediaBox.HandlerBox.pre_defined = 0; + swap = bytereverse('soun'); + moov->TrackBox[numtrack].MediaBox.HandlerBox.handler_type = swap; + moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[0] = 0; + moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[1] = 0; + moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[2] = 0; + //swap = bytereverse('soun'); + //moov->TrackBox[numtrack].MediaBox.HandlerBox.data = swap; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[0] = 's'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[1] = 'o'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[2] = 'u'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[3] = 'n'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[4] = '\0'; + + //Media Header Box// + sizeMDHD = 32; + swap = bytereverse(sizeMDHD); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.size = swap; + swap = bytereverse('mdhd'); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.version = 0; + swap = bytereverse(clock); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.creation_time = swap; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.modification_time = swap; + swap = bytereverse(1000); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.timescale = swap; + swap = bytereverse(durationTrack); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.duration = swap; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.language = 0xC455; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.pre_defined = 0; + + //Media Box// + sizeMDIA = sizeMDHD + sizeHDLR + sizeMINF + 8; + swap = bytereverse(sizeMDIA); + moov->TrackBox[numtrack].MediaBox.size = swap; + swap = bytereverse('mdia'); + moov->TrackBox[numtrack].MediaBox.type = swap; + + //Track Header// + sizeTKHD = 92; + swap = bytereverse (sizeTKHD); + moov->TrackBox[numtrack].TrackHeaderBox.size = swap; + swap = bytereverse ('tkhd'); + moov->TrackBox[numtrack].TrackHeaderBox.type = swap ; + swap = bytereverse (0x00000006); + moov->TrackBox[numtrack].TrackHeaderBox.version = swap; + swap = bytereverse (clock); + moov->TrackBox[numtrack].TrackHeaderBox.creation_time = swap; + moov->TrackBox[numtrack].TrackHeaderBox.modification_time = swap; + swap = bytereverse (numtrack+1); + moov->TrackBox[numtrack].TrackHeaderBox.track_ID = swap; //From 0x00000001 - 0x7FFFFFFF (dec 2147483647) + moov->TrackBox[numtrack].TrackHeaderBox.reserved = 0; + swap = bytereverse (durationTrack); + moov->TrackBox[numtrack].TrackHeaderBox.duration = swap; + moov->TrackBox[numtrack].TrackHeaderBox.reserved2[0] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.reserved2[1] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.layer = 0; + moov->TrackBox[numtrack].TrackHeaderBox.alternate_group = 0; + moov->TrackBox[numtrack].TrackHeaderBox.volume = 0x1; + moov->TrackBox[numtrack].TrackHeaderBox.reserved3 = 0; + swap = bytereverse (0x00010000); + moov->TrackBox[numtrack].TrackHeaderBox.matrix[0] = swap; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[1] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[2] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[3] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[4] = swap; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[5] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[6] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[7] = 0; + swap = bytereverse(0x40000000); + moov->TrackBox[numtrack].TrackHeaderBox.matrix[8] = swap; + moov->TrackBox[numtrack].TrackHeaderBox.width = 0; //just for video + moov->TrackBox[numtrack].TrackHeaderBox.height = 0; //just for video + + //Track container + sizeTRAK = sizeTKHD + sizeMDIA + 8; + swap = bytereverse (sizeTRAK); // Size of one track + moov->TrackBox[numtrack].size = swap; + swap = bytereverse ('trak'); + moov->TrackBox[numtrack].type = swap; + return sizeTRAK; + +} + +int groupcontainer(MovieBox *moov, int *group_tracks, int grp_vol, QString grp_name, + QString grp_description, int totaltracks) { + + int i, j, k, numgroups, sizeCont; + int numel = 0; + int sizeBox = 0; + int tempsize = 0; + int active, activenum, addsize; + +// ADDED FOR SV + for (j=0; jGroupContainerBox.num_groups = bytereverse16(numgroups); + + for (i=0; iGroupContainerBox.GroupBox[i].group_ID = bytereverse(2147483649+i+1); // group_ID shall be represented from 0x80000000 to 0xFFFFFFFF + strcpy(moov->GroupContainerBox.GroupBox[i].group_name, grp_name.toStdString().c_str()); + strcpy(moov->GroupContainerBox.GroupBox[i].group_description, grp_description.toStdString().c_str()); + +// numel = 0; // uncomment for more than one group and remove initial "for" with numel + k = 0; + for (j=0; jGroupContainerBox.GroupBox[i].groupElemId[k].element_ID = bytereverse(j+1); +// numel++; // uncomment for more than one group and remove initial "for" with numel + addsize += 4; + k++; + } + } + moov->GroupContainerBox.GroupBox[i].num_elements = bytereverse16(numel); + +// printf("Choose the activation mode: "); +// printf("Activation mode\n"); +// printf(" - Switch on the MINIMUN number of elements (0, if no Min/Max rule) [0]\n"); +// printf(" - Switch on the MAXIMUM number of elements (All tracks, if no Min/Max rule) [1]\n"); +// printf(" - Switch on the defined number of elements (ONLY IF there is Min/Max rule) [2]\n"); +// scanf("%d",&active); +// fflush(stdin); + + active = 1; // ADDED FOR SV, All tracks enabled + + moov->GroupContainerBox.GroupBox[i].group_activation_mode = active; + activenum = 0; + moov->GroupContainerBox.GroupBox[i].group_activation_elements_number = activenum; + if (active==2){ + printf("Activation elements number: "); + scanf("%d",&activenum); + moov->GroupContainerBox.GroupBox[i].group_activation_elements_number = bytereverse16(activenum); + addsize += 2; + } + + moov->GroupContainerBox.GroupBox[i].group_reference_volume = bytereverse16(grp_vol*256/100); // define 8.8 fixed point + + tempsize = 75 + addsize; // ---> before was 66 + addsize; + moov->GroupContainerBox.GroupBox[i].size = bytereverse(tempsize); + moov->GroupContainerBox.GroupBox[i].type = bytereverse('grup'); + moov->GroupContainerBox.GroupBox[i].version = bytereverse(0x02); // flags = Display enable, Edit disable + + sizeBox += tempsize; + + } // close for (numgroups) + + sizeCont = sizeBox + 10; + + moov->GroupContainerBox.size = bytereverse(sizeCont); + moov->GroupContainerBox.type = bytereverse('grco'); + + return sizeCont; +} + +int presetcontainer(MovieBox *moov, int totaltracks, int *vol_values, int prestype, int fade_in){ + + int temp, i, j, k, m, t, vol; + int numpres, eq; + //char name[50]; + u32 sizePRST = 0; + u32 sizePRCO = 0; + u32 sizeEQ; + u32 addsize = 0; + int updates = 0; + + numpres = 1; // ADDED FOR SV + + //Preset Box// + for (i=0; iPresetContainerBox.PresetBox[i].type = bytereverse('prst'); + moov->PresetContainerBox.PresetBox[i].flags = bytereverse(0x02); // Display Enable Edit Disable + moov->PresetContainerBox.PresetBox[i].preset_ID = i+1; + moov->PresetContainerBox.PresetBox[i].num_preset_elements = totaltracks; // All the tracks are involved in the preset + for (j=0; jPresetContainerBox.PresetBox[i].presElemId[j].preset_element_ID = bytereverse(j+1); + } + moov->PresetContainerBox.PresetBox[i].preset_global_volume = 100; + +// prestype = 0; // ADDED FOR SV + + switch (prestype) { + case 0: moov->PresetContainerBox.PresetBox[i].preset_type = 0; + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Static track volume preset"); + + for (j=0; jPresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].preset_volume_element = vol/2; //*0.02 + } + + addsize = totaltracks; + break; + case 1: moov->PresetContainerBox.PresetBox[i].preset_type = 1; + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Static object volume preset"); + + for (j=0; jPresetContainerBox.PresetBox[i].StaticObjectVolume.InputCH[j].num_input_channel = num_ch; + } + moov->PresetContainerBox.PresetBox[i].StaticObjectVolume.output_channel_type = 1; // STEREO (2 output channels) + for (j=0; jPresetContainerBox.PresetBox[i].StaticObjectVolume.presElVol[j]. + Input[k].Output[m].preset_volume_element = (100-(20*m))/2; // INPUT BY USER + } + } + } + + addsize = totaltracks + 1+ totaltracks*num_ch*num_ch; + break; + case 2: moov->PresetContainerBox.PresetBox[i].preset_type = 2; + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic track volume preset"); + + updates = 2; // volume changes + moov->PresetContainerBox.PresetBox[i].DynamicTrackVolume.num_updates = bytereverse16(updates); + for (j=0; jPresetContainerBox.PresetBox[i].DynamicTrackVolume. + DynamicChange[j].updated_sample_number = bytereverse16(100+(j*100)); // *0.026 = time in seconds + for (k=0; kPresetContainerBox.PresetBox[i].DynamicTrackVolume. + DynamicChange[j].presVolumElem[k].preset_volume_element = (50*j)/2; // INPUT BY USER + } + } + + addsize = 2 + updates*(2 + totaltracks); + break; + case 3: moov->PresetContainerBox.PresetBox[i].preset_type = 3; + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic object volume preset"); + + updates = 2; // volume changes + moov->PresetContainerBox.PresetBox[i].DynamicObjectVolume.num_updates = bytereverse16(updates); // INPUT BY USER (maybe...) + for (j=0; jPresetContainerBox.PresetBox[i].DynamicObjectVolume.InputCH[j].num_input_channel = 2; + } + moov->PresetContainerBox.PresetBox[i].DynamicObjectVolume.output_channel_type = 1; // STEREO (2 output channels) + for (j=0; jPresetContainerBox.PresetBox[i].DynamicObjectVolume. + DynamicChange[j].updated_sample_number = bytereverse16(0+(j*500)); // *0.026 = time in seconds + for (k=0; kPresetContainerBox.PresetBox[i].DynamicObjectVolume.DynamicChange[j]. + presElVol[k].Input[m].Output[t].preset_volume_element = (25*(j+1)); // INPUT BY USER + } + } + } + } + + addsize = 2 + totaltracks + 1 + updates*(2 + totaltracks*num_ch*num_ch); + break; + case 4: moov->PresetContainerBox.PresetBox[i].preset_type = 4; + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic track approximated volume"); + + updates = 2; // volume changes + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.num_updates = bytereverse16(updates); + for (j=0; jPresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].start_sample_number = bytereverse16(100); // *0.026 = time in seconds - INPUT BY USER + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].duration_update = bytereverse16(500); // *0.026 = time in seconds -INPUT BY USER + for (k=0; kPresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[j]. + presElVol[k].end_preset_volume_element = (50*j); // Fade IN + } else { + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[j]. + presElVol[k].end_preset_volume_element = (100-(100*j))/2; // Fade OUT + } + } + } + + /* // some code for test + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[2].start_sample_number = bytereverse16(1100); + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[2].duration_update = bytereverse16(250); + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[2].presElVol[0].end_preset_volume_element = 50; + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[2].presElVol[1].end_preset_volume_element = 50; + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[3].start_sample_number = bytereverse16(1100); + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[3].duration_update = bytereverse16(250); + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[3].presElVol[0].end_preset_volume_element = 1; + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[3].presElVol[1].end_preset_volume_element = 1; + */ + + addsize = 2 + updates*(2 + 2 + totaltracks); + break; + case 5: moov->PresetContainerBox.PresetBox[i].preset_type = 5; // NOT YET IMPLEMENTED INTO THE PLAYER! + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic object approximated volume"); + + printf("\n\nTHIS PRESET IS NOT YET IMPLEMENTED INTO THE PLAYER!!! PLAYER MAY CRASH WITH THIS FILE!!!\n\n"); + + updates = 2; // volume changes + moov->PresetContainerBox.PresetBox[i].DynamicObjectApproxVolume.num_updates = bytereverse16(updates); + for (j=0; jPresetContainerBox.PresetBox[i].DynamicObjectApproxVolume.InputCH[j].num_input_channel = 2; + } + moov->PresetContainerBox.PresetBox[i].DynamicObjectApproxVolume.output_channel_type = 1; // STEREO (2 output channels) + for (j=0; jPresetContainerBox.PresetBox[i].DynamicObjectApproxVolume. + DynamicChange[j].start_sample_number = bytereverse16(100); // *0.026 = time in seconds - INPUT BY USER + moov->PresetContainerBox.PresetBox[i].DynamicObjectApproxVolume. + DynamicChange[j].duration_update = bytereverse16(250); // *0.026 = time in seconds - INPUT BY USER + for (k=0; kPresetContainerBox.PresetBox[i].DynamicObjectApproxVolume.DynamicChange[j]. + presElVol[k].Input[m].Output[t].preset_volume_element = (100*j)/2; // INPUT BY USER + } + } + } + } + + addsize = 2 + totaltracks + 1 + updates*( 2 + 2 + totaltracks*num_ch*num_ch); + break; + case 6: moov->PresetContainerBox.PresetBox[i].preset_type = 8; + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Static track volume with Equalization"); + + eq = 0; addsize = 0; + for (j=0; jPresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].preset_volume_element = vol/2; //*0.02 + + // Equalization + printf("EQ Filter on this element? [1] Yes - [0] No : "); + scanf("%d",&eq); + fflush(stdin); + + if (eq == 1){ + moov->PresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].EQ.num_eq_filters = 1; + for (k=0; kPresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].EQ.num_eq_filters; k++){ + moov->PresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].EQ.Filter[k].filter_type = 4; // HPF + moov->PresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].EQ.Filter[k]. + filter_reference_frequency = bytereverse16(5000); // 10kHz + moov->PresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].EQ.Filter[k].filter_gain = -10; + moov->PresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].EQ.Filter[k].filter_bandwidth = 4; + addsize += 5; + } //close for + }else{ + moov->PresetContainerBox.PresetBox[i].StaticTrackVolume.presVolumElem[j].EQ.num_eq_filters = 0; + } //close if/else + } //close for + + addsize += totaltracks + totaltracks; //add preset_volume and num_eq_filters size + break; + case 7: moov->PresetContainerBox.PresetBox[i].preset_type = 9; // NOT YET IMPLEMENTED INTO THE PLAYER! + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Static object volume with Equalization"); + printf("\n\nTHIS PRESET IS NOT YET IMPLEMENTED INTO THE PLAYER!!! PLAYER MAY CRASH WITH THIS FILE!!!\n\n"); + break; + case 8: moov->PresetContainerBox.PresetBox[i].preset_type = 10; // NOT YET IMPLEMENTED INTO THE PLAYER! + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic track volume with Equalization"); + printf("\n\nTHIS PRESET IS NOT YET IMPLEMENTED INTO THE PLAYER!!! PLAYER MAY CRASH WITH THIS FILE!!!\n\n"); + break; + case 9: moov->PresetContainerBox.PresetBox[i].preset_type = 11; // NOT YET IMPLEMENTED INTO THE PLAYER! + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic object volume with Equalization"); + break; + case 10: moov->PresetContainerBox.PresetBox[i].preset_type = 12; // NOT YET IMPLEMENTED INTO THE PLAYER! + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic track approximated with Equalization"); + printf("\n\nTHIS PRESET IS NOT YET IMPLEMENTED INTO THE PLAYER!!! PLAYER MAY CRASH WITH THIS FILE!!!\n\n"); + + eq = 0; addsize = 0; + updates = 2; // volume changes + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.num_updates = bytereverse16(updates); + for (j=0; jPresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].start_sample_number = bytereverse16(100); // *0.026 = time in seconds - INPUT BY USER + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].duration_update = bytereverse16(500); // *0.026 = time in seconds -INPUT BY USER + for (k=0; kPresetContainerBox.PresetBox[i].DynamicTrackApproxVolume.DynamicChange[j]. + presElVol[k].end_preset_volume_element = (50*j); // Fade IN, change in (100-(100*j))/2 for Fade OUT -INPUT BY USER + + // Equalization + //printf("EQ Filter on %s ? [1] Yes - [0] No : ",namet[k].title); + scanf("%d",&eq); + fflush(stdin); + + if (eq == 1){ + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].presElVol[k].EQ.num_eq_filters = 1; + for (t=0; tPresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].presElVol[k].EQ.num_eq_filters; t++){ + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].presElVol[k].EQ.Filter[t].filter_type = 4; // HPF + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].presElVol[k].EQ.Filter[t].filter_reference_frequency = bytereverse16(5000); // 10kHz + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].presElVol[k].EQ.Filter[t].end_filter_gain = -10; + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].presElVol[k].EQ.Filter[t].filter_bandwidth = 4; + addsize += 5; + } //close for + }else{ + moov->PresetContainerBox.PresetBox[i].DynamicTrackApproxVolume. + DynamicChange[j].presElVol[k].EQ.num_eq_filters = 0; + } //close if/else + } //close for (k) + } //close for (j) + + addsize += 2 + updates*(2 + 2 + totaltracks*(1+1)); + break; + case 11: moov->PresetContainerBox.PresetBox[i].preset_type = 13; // NOT YET IMPLEMENTED INTO THE PLAYER! + strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, "Dynamic object approximated with Equalization"); + printf("\n\nTHIS PRESET IS NOT YET IMPLEMENTED INTO THE PLAYER!!! PLAYER MAY CRASH WITH THIS FILE!!!\n\n"); + break; + default: printf("ERROR in PRESET CONTAINER"); + system("pause"); + exit(1); + break; + + } //close switch + + temp = 16 + 50 + 4*totaltracks + addsize; // size PresetBox[i] + moov->PresetContainerBox.PresetBox[i].size = bytereverse(temp); + + sizePRST += temp; // size of all Preset Boxes + + } //close for + + //Preset Container// + sizePRCO += sizePRST + 10; + moov->PresetContainerBox.size = bytereverse(sizePRCO); + moov->PresetContainerBox.type = bytereverse('prco'); + moov->PresetContainerBox.default_preset_ID = 1; // Indicates initial preset activated. + moov->PresetContainerBox.num_preset = numpres; + + return sizePRCO; + +} //close function + +int rulescontainer(MovieBox *moov, int SelRuleType, int SelRule_PAR1, int SelRule_PAR2, + int MixRuleType, int MixRule_PAR1, int MixRule_PAR2, + int MixRule_PAR3, int MixRule_PAR4) { + + int swap; + u32 add_size = 0; //for SelectionRulesBox + u32 sizeRUSC, sizeRUCO, sizeRUMX; + + + //Selection Rules + moov->RulesContainer.num_selection_rules = bytereverse16(1); + moov->RulesContainer.SelectionRules.selection_rule_ID = bytereverse16(1); + + switch (SelRuleType) { + + case 0: moov->RulesContainer.SelectionRules.selection_rule_type = 0; + moov->RulesContainer.SelectionRules.element_ID = bytereverse(2147483649+1); // Must be the same ID of the group + moov->RulesContainer.SelectionRules.min_num_elements = bytereverse16(SelRule_PAR1); + moov->RulesContainer.SelectionRules.max_num_elements = bytereverse16(SelRule_PAR2); + strcpy(moov->RulesContainer.SelectionRules.rule_description,"Min/Max Rule"); + add_size = 4; + break; + case 1: moov->RulesContainer.SelectionRules.selection_rule_type = 1; + moov->RulesContainer.SelectionRules.element_ID = bytereverse(SelRule_PAR1); + moov->RulesContainer.SelectionRules.key_element_ID =bytereverse(SelRule_PAR2); + strcpy(moov->RulesContainer.SelectionRules.rule_description,"Exclusion Rule"); + add_size = 4; + break; + case 2: moov->RulesContainer.SelectionRules.selection_rule_type = 2; + moov->RulesContainer.SelectionRules.element_ID = bytereverse(SelRule_PAR1); + strcpy(moov->RulesContainer.SelectionRules.rule_description,"Not mute Rule"); + add_size = 0; + break; + case 3: moov->RulesContainer.SelectionRules.selection_rule_type = 3; + moov->RulesContainer.SelectionRules.element_ID = bytereverse(SelRule_PAR1); + moov->RulesContainer.SelectionRules.key_element_ID =bytereverse(SelRule_PAR2); + strcpy(moov->RulesContainer.SelectionRules.rule_description,"Implication Rule"); + add_size = 4; + break; + default: printf("ERROR in RULES CONTAINER/Selection Rules"); + system("pause"); + break; + } + + sizeRUSC = 19 + 20 + add_size; + moov->RulesContainer.SelectionRules.size = bytereverse(sizeRUSC); + moov->RulesContainer.SelectionRules.type = bytereverse('rusc'); + moov->RulesContainer.SelectionRules.version = 0; + + //Mixing Rule + moov->RulesContainer.num_mixing_rules = bytereverse16(1); + moov->RulesContainer.MixingRules.mixing_rule_ID = bytereverse16(1); + + switch (MixRuleType) { + + case 0: moov->RulesContainer.MixingRules.mixing_type = 0; + moov->RulesContainer.MixingRules.element_ID = bytereverse(MixRule_PAR1); + moov->RulesContainer.MixingRules.key_elem_ID = bytereverse(MixRule_PAR2); + strcpy(moov->RulesContainer.MixingRules.mix_description, "Equivalence rule"); + break; + case 1: moov->RulesContainer.MixingRules.mixing_type = 1; + moov->RulesContainer.MixingRules.element_ID = bytereverse(MixRule_PAR2); + moov->RulesContainer.MixingRules.key_elem_ID = bytereverse(MixRule_PAR1); + strcpy(moov->RulesContainer.MixingRules.mix_description, "Upper rule"); + break; + case 2: moov->RulesContainer.MixingRules.mixing_type = 2; + moov->RulesContainer.MixingRules.element_ID = bytereverse(MixRule_PAR2); + moov->RulesContainer.MixingRules.key_elem_ID = bytereverse(MixRule_PAR1); + strcpy(moov->RulesContainer.MixingRules.mix_description, "Lower rule"); + break; + case 3: moov->RulesContainer.MixingRules.mixing_type = 3; + moov->RulesContainer.MixingRules.element_ID = bytereverse(MixRule_PAR1); + moov->RulesContainer.MixingRules.min_volume = bytereverse16(1 + MixRule_PAR3*2.5); // 8.8 fixed point + moov->RulesContainer.MixingRules.max_volume = bytereverse16(1 + MixRule_PAR4*2.5); // 8.8 fixed point + strcpy(moov->RulesContainer.MixingRules.mix_description, "Limit rule"); + break; + default: printf("ERROR in RULES CONTAINER/Mixing Rules"); + system("pause"); + exit(1); + break; + } + + sizeRUMX = 23 + 17; + moov->RulesContainer.MixingRules.size = bytereverse(sizeRUMX); + moov->RulesContainer.MixingRules.type = bytereverse('rumx'); + moov->RulesContainer.MixingRules.version = 0; + + //Rule container + sizeRUCO = 12 + sizeRUSC + sizeRUMX; + swap = bytereverse(sizeRUCO); + moov->RulesContainer.size = swap; + swap = bytereverse('ruco'); + moov->RulesContainer.type = swap; + + return sizeRUCO; + +} // close function + +void moovheaderbox (MovieBox *moov, int clock, int sizeTRAK, int sizePRCO, int totaltracks, + int durationTrack, int sizeRUCO, int sizeGRCO) { + int swap; + u32 sizeMOOV; //MovieBox + + //MovieHeader + u32 sizeMVHD = 108; + swap = bytereverse (sizeMVHD); + moov->MovieHeaderBox.size = swap; + swap = bytereverse ('mvhd'); + moov->MovieHeaderBox.type = swap; + moov->MovieHeaderBox.version = 0; + swap = bytereverse (clock); + moov->MovieHeaderBox.creation_time = swap; + moov->MovieHeaderBox.modification_time = swap; + swap = bytereverse (1000); + moov->MovieHeaderBox.timescale = swap; + swap = bytereverse (durationTrack); + moov->MovieHeaderBox.duration = swap; + swap = bytereverse (0x00010000); + moov->MovieHeaderBox.rate = swap; + swap = bytereverse (1); + moov->MovieHeaderBox.volume = 1; + moov->MovieHeaderBox.reserved=0; + moov->MovieHeaderBox.reserved2[0] = 0; + moov->MovieHeaderBox.reserved2[1] = 0; + swap = bytereverse (0x00010000); + moov->MovieHeaderBox.matrix[0] = swap; + moov->MovieHeaderBox.matrix[1] = 0; + moov->MovieHeaderBox.matrix[2] = 0; + moov->MovieHeaderBox.matrix[3] = 0; + moov->MovieHeaderBox.matrix[4] = swap; + moov->MovieHeaderBox.matrix[5] = 0; + moov->MovieHeaderBox.matrix[6] = 0; + moov->MovieHeaderBox.matrix[7] = 0; + swap = bytereverse (0x40000000); + moov->MovieHeaderBox.matrix[8] = 0x40000000; + moov->MovieHeaderBox.pre_defined[0] = 0; + moov->MovieHeaderBox.pre_defined[1] = 0; + moov->MovieHeaderBox.pre_defined[2] = 0; + moov->MovieHeaderBox.pre_defined[3] = 0; + moov->MovieHeaderBox.pre_defined[4] = 0; + moov->MovieHeaderBox.pre_defined[5] = 0; + swap = bytereverse (totaltracks + 1); + moov->MovieHeaderBox.next_track_ID = swap; + + //MovieBox + sizeMOOV = sizeMVHD + sizeTRAK + sizePRCO + sizeRUCO + sizeGRCO + 8; + swap = bytereverse (sizeMOOV); //Size movie: Taking into account number tracks + moov->size = swap; + swap = bytereverse ('moov'); + moov->type = swap; +} + + +void writemoovbox(MovieBox moov, int numtrack,int totaltracks, FILE *imf, FILE *text, bool HasTextFile) +{ + int i, j, k, m, t, swap, pos, temp, type; + int cnt = 0, cnt2 = 0, d = 0, dat = 0, dat1 = 0, dat2 = 0, dat3 = 0, size = 0; + u16 numgroups, numel; + + + //Write movie box// + fwrite(&moov.size, sizeof(u32), 1, imf); + fwrite(&moov.type, sizeof(u32), 1, imf); + //Movie header// + fwrite(&moov.MovieHeaderBox, sizeof(moov.MovieHeaderBox), 1, imf); + //Track container// + for (numtrack = 0; numtrack < totaltracks; numtrack++) { + fwrite(&moov.TrackBox[numtrack].size, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].type, sizeof(u32), 1, imf); + //Trck header// + fwrite(&moov.TrackBox[numtrack].TrackHeaderBox, sizeof(moov.TrackBox[numtrack].TrackHeaderBox), 1, imf); + //Media Box// + fwrite(&moov.TrackBox[numtrack].MediaBox.size, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.type, sizeof(u32), 1, imf); + //Media Header// + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaHeaderBox, + sizeof(moov.TrackBox[numtrack].MediaBox.MediaHeaderBox), 1, imf); + //Handler Box// + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.size, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.type, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.version, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.pre_defined, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.handler_type, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.reserved[0], sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.reserved[1], sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.reserved[2], sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.data[0], sizeof(unsigned char), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.data[1], sizeof(unsigned char), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.data[2], sizeof(unsigned char), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.data[3], sizeof(unsigned char), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.HandlerBox.data[4], sizeof(unsigned char), 1, imf); + //Media inforamtion box// + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.size, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.type, sizeof(u32), 1, imf); + //Sound media header// + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox, + sizeof(moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox), 1, imf); + //Data reference// + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox, + sizeof(moov.TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox), 1, imf); + //Sample table box// + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.size, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.type, sizeof(u32), 1, imf); + + //Time to sample box// + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.size, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.type, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.version, sizeof(u32), 1, imf); + fwrite(&moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.entry_count, sizeof(u32), 1, imf); + + swap = bytereverse(moov.TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.entry_count); + pos = swap; + + for (i=0; iIMAF SongEncoderQMULFrank Sinatra2013Electro 0711"; + + sizeDINF = 8;// + sizeDREF + sizeURL; + sizeIINF = 14 + sizeINFE; + sizeMETA = 12 + sizeHDLR + sizeDINF + sizeILOC + sizeIINF + sizeXML; + + meta->size = bytereverse(sizeMETA); + meta->type = bytereverse('meta'); + meta->version = 0; + //HandlerBox + meta->theHandler.size = bytereverse(sizeHDLR); + meta->theHandler.type = bytereverse('hdlr'); + meta->theHandler.version = 0; + meta->theHandler.pre_defined = 0; + meta->theHandler.handler_type = bytereverse('meta'); + meta->theHandler.reserved[0] = 0; + meta->theHandler.reserved[1] = 0; + meta->theHandler.reserved[2] = 0; + meta->theHandler.name[0] = bytereverse('m'); + meta->theHandler.name[1] = bytereverse('p'); + meta->theHandler.name[2] = bytereverse('7'); + meta->theHandler.name[3] = bytereverse('t'); + //DataInformationBox + meta->file_locations.size = bytereverse(sizeDINF); + meta->file_locations.type = bytereverse('dinf'); + /* + //DataReferenceBox + meta->file_locations.DataReferenceBox.size = bytereverse(sizeDREF); + meta->file_locations.DataReferenceBox.type = bytereverse('dref'); + meta->file_locations.DataReferenceBox.flags = bytereverse(0); // CHECK THIS VALUE + meta->file_locations.DataReferenceBox.entry_count = bytereverse(1); + //DataEntryUrlBox + meta->file_locations.DataReferenceBox.DataEntryUrlBox.size = bytereverse(sizeURL); + meta->file_locations.DataReferenceBox.DataEntryUrlBox.type = bytereverse('url '); // 'url ' with blank space + meta->file_locations.DataReferenceBox.DataEntryUrlBox.flags = bytereverse(0); // CHECK THIS VALUE + */ + //item_location + meta->item_locations.size = bytereverse(sizeILOC); + meta->item_locations.type = bytereverse('iloc'); + meta->item_locations.version = 0; + meta->item_locations.offset_size = 68; // 0100|0100 offset_size = 4 + lenght_size = 4 + //meta->item_locations.lenght_size = 4; //already included + meta->item_locations.base_offset_size = 64; // 0100|0000 base_offset_size = 4 + reserved = 0 + //meta->item_locations.reserved = 0; //already included + meta->item_locations.item_count = bytereverse16(1); + meta->item_locations.item_ID = bytereverse16(1); + meta->item_locations.data_reference_index = 0; + //meta->item_locations.base_offset = bytereverse(); // corresponding to iloc_offset in insertImage function + meta->item_locations.extent_count = bytereverse16(1); + //meta->item_locations.extent_offset = bytereverse(); // corresponding to iloc_offset in insertImage function + //meta->item_locations.extent_length = bytereverse(); // corresponding to imagesize in insertImage function + + //ItemInfoBox + meta->item_infos.size = bytereverse(sizeIINF); + meta->item_infos.type = bytereverse('iinf'); + meta->item_infos.version = 0; + meta->item_infos.entry_count = bytereverse16(1); + + //info_entry + meta->item_infos.info_entry.size = bytereverse(sizeINFE); + meta->item_infos.info_entry.type = bytereverse('infe'); + meta->item_infos.info_entry.version = 0; + meta->item_infos.info_entry.item_ID = bytereverse16(1); + meta->item_infos.info_entry.item_protection_index = 0; + strcpy(meta->item_infos.info_entry.item_name, name); + strcpy(meta->item_infos.info_entry.content_type, type_content); + strcpy(meta->item_infos.info_entry.content_encoding, encoding); + + //XMLBox (MetaData) + meta->XMLBox.size = bytereverse(sizeXML); + meta->XMLBox.type = bytereverse('xml '); + meta->XMLBox.version = 0; + strcpy(meta->XMLBox.string, xml); + + return sizeMETA; +} + +//Read the image's size +u32 getImageSize(const char *imagedir){ + u32 size; + FILE *img; + + img = fopen(imagedir,"rb"); + + //Calculate size of the picture + fseek(img,0,SEEK_END); + size = ftell(img); + fclose(img); + + return size; +} +//Read the text´s size +int getTextSize (FILE *text){ + + int d=0,sizetext=0,dat=0,dat1=0,dat2=0,dat3=0; + + //TEXT-FILE + //Find mdat in text file in order to know the size of the text file + d=0; + while(d==0){ + + fread (&dat,sizeof(unsigned char),1,text); //read a byte and saves it in dat + fread (&dat1,sizeof(unsigned char),1,text); + fread (&dat2,sizeof(unsigned char),1,text); + fread (&dat3,sizeof(unsigned char),1,text); + fseek(text,-3,SEEK_CUR); + + if(dat == 0x6D && dat1 == 0x64 && dat2 == 0x61 && dat3 == 0x74){ // 6D646174 = mdat + d=1; + } + + } //close while + + fseek (text,-5,SEEK_CUR);//positionate the pointer at the first byte of size + fread (&dat,sizeof(unsigned char),1,text); //first byte of size + fread (&dat1,sizeof(unsigned char),1,text);//second byte of size + fread (&dat2,sizeof(unsigned char),1,text);//third byte of size + fread (&dat3,sizeof(unsigned char),1,text);//fourth byte of size + + sizetext = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + sizetext = sizetext-8-16; //4 bytes of size and 4 bytes of type and 16 bytes of padding + + fseek (text,20,SEEK_CUR);//Advance 20 bytes, because the pointer must advance 20 bytes to read the size of the first string.This is because of the way that Quicktime creates the 3gp + + return sizetext; + + +} + +//Read the JPEG file + +void insertImage (MetaBox *meta, FILE **imf, u32 imagesize, const char *imagedir) { + + FILE *img; + u64 iloc_offset = 0; + unsigned char *imgbuffer; + + img = fopen(imagedir,"rb"); + + // Binary reading + fseek(img,0,SEEK_SET); + imgbuffer= (unsigned char*)malloc(sizeof(unsigned char)*imagesize); + fread(imgbuffer, 1, imagesize, img); + fclose(img); + + // Find position in the IMAF file and write the image + iloc_offset = ftell(*imf); + fwrite(imgbuffer,1,imagesize, *imf); + + // Set image size and offset values + meta->item_locations.base_offset = bytereverse(iloc_offset); + meta->item_locations.extent_length = bytereverse(imagesize); + meta->item_locations.extent_offset = bytereverse(iloc_offset); + +} + + +void writemetabox(MetaBox meta, FILE *imf) { + + int i=0; + + //MetaBox + fwrite(&meta.size, sizeof(u32), 1, imf); + fwrite(&meta.type, sizeof(u32), 1, imf); + fwrite(&meta.version, sizeof(u32), 1, imf); + //Handler + fwrite(&meta.theHandler.size, sizeof(u32), 1, imf); + fwrite(&meta.theHandler.type, sizeof(u32), 1, imf); + fwrite(&meta.theHandler.version, sizeof(u32), 1, imf); + fwrite(&meta.theHandler.pre_defined, sizeof(u32), 1, imf); + fwrite(&meta.theHandler.handler_type, sizeof(u32), 1, imf); + fwrite(&meta.theHandler.reserved[0], sizeof(u32), 1, imf); + fwrite(&meta.theHandler.reserved[1], sizeof(u32), 1, imf); + fwrite(&meta.theHandler.reserved[2], sizeof(u32), 1, imf); + fwrite(&meta.theHandler.name[0], sizeof(unsigned char), 1, imf); + fwrite(&meta.theHandler.name[1], sizeof(unsigned char), 1, imf); + fwrite(&meta.theHandler.name[2], sizeof(unsigned char), 1, imf); + fwrite(&meta.theHandler.name[3], sizeof(unsigned char), 1, imf); + //Data Information Box + fwrite(&meta.file_locations.size, sizeof(u32), 1, imf); + fwrite(&meta.file_locations.type, sizeof(u32), 1, imf); + /* + //Data Reference + fwrite(&meta.file_locations.DataReferenceBox.size, sizeof(u32), 1, imf); + fwrite(&meta.file_locations.DataReferenceBox.type, sizeof(u32), 1, imf); + fwrite(&meta.file_locations.DataReferenceBox.flags, sizeof(u32), 1, imf); + fwrite(&meta.file_locations.DataReferenceBox.entry_count, sizeof(u32), 1, imf); + + fwrite(&meta.file_locations.DataReferenceBox.DataEntryUrlBox.size, sizeof(u32), 1, imf); + fwrite(&meta.file_locations.DataReferenceBox.DataEntryUrlBox.type, sizeof(u32), 1, imf); + fwrite(&meta.file_locations.DataReferenceBox.DataEntryUrlBox.flags, sizeof(u32), 1, imf); + */ + //Item Location Box + fwrite(&meta.item_locations.size, sizeof(u32), 1, imf); + fwrite(&meta.item_locations.type, sizeof(u32), 1, imf); + fwrite(&meta.item_locations.version, sizeof(u32), 1, imf); + fwrite(&meta.item_locations.offset_size, sizeof(unsigned char), 1, imf); + //fwrite(&meta.item_locations.lenght_size, sizeof(unsigned char), 1, imf); + fwrite(&meta.item_locations.base_offset_size, sizeof(unsigned char), 1, imf); + //fwrite(&meta.item_locations.reserved, sizeof(unsigned char), 1, imf); + fwrite(&meta.item_locations.item_count, sizeof(u16), 1, imf); + fwrite(&meta.item_locations.item_ID, sizeof(u16), 1, imf); + fwrite(&meta.item_locations.data_reference_index, sizeof(u16), 1, imf); + fwrite(&meta.item_locations.base_offset, sizeof(u32), 1, imf); + fwrite(&meta.item_locations.extent_count, sizeof(u16), 1, imf); + fwrite(&meta.item_locations.extent_offset, sizeof(u32), 1, imf); + fwrite(&meta.item_locations.extent_length, sizeof(u32), 1, imf); + //Item Info + fwrite(&meta.item_infos.size, sizeof(u32), 1, imf); + fwrite(&meta.item_infos.type, sizeof(u32), 1, imf); + fwrite(&meta.item_infos.version, sizeof(u32), 1, imf); + fwrite(&meta.item_infos.entry_count, sizeof(u16), 1, imf); + //Info Entry + fwrite(&meta.item_infos.info_entry.size, sizeof(u32), 1, imf); + fwrite(&meta.item_infos.info_entry.type, sizeof(u32), 1, imf); + fwrite(&meta.item_infos.info_entry.version, sizeof(u32), 1, imf); + fwrite(&meta.item_infos.info_entry.item_ID, sizeof(u16), 1, imf); + fwrite(&meta.item_infos.info_entry.item_protection_index, sizeof(u16), 1, imf); + for (i=0; i<6; i++){ + fwrite(&meta.item_infos.info_entry.item_name[i], sizeof(char), 1, imf); + } + for (i=0; i<18; i++){ + fwrite(&meta.item_infos.info_entry.content_type[i], sizeof(char), 1, imf); + } + for (i=0; i<4; i++){ + fwrite(&meta.item_infos.info_entry.content_encoding[i], sizeof(char), 1, imf); + } + //XML for metadata + fwrite(&meta.XMLBox.size, sizeof(u32), 1, imf); + fwrite(&meta.XMLBox.type, sizeof(u32), 1, imf); + fwrite(&meta.XMLBox.version, sizeof(u32), 1, imf); + for(i=0; i<2000; i++){ + fwrite(&meta.XMLBox.string[i], sizeof(char), 1, imf); + } + +} + +//TIMED-TEXT's funcionts +int trackstructure_text (MovieBox *moov, int numtrack, int clock, + int durationTrack, int sizemdat, const char *textfile,FILE *text,int totaltracks ) { // creates the text trak structure + int swap; + u32 sizeURL; + u32 sizeDREF; + u32 sizeDINF; + u32 sizeSMHD; + u32 sizeMINF; + u32 sizeHDLR; + u32 sizeMDHD; + u32 sizeMDIA; + u32 sizeTKHD; + u32 sizeTRAK; + + + //Sample Table Box + int sizeSTBL = 0; + + sizeSTBL = samplecontainer_text(moov, numtrack,sizemdat, textfile,totaltracks); + + //Data Entry Url Box + sizeURL = 12; + swap = bytereverse(sizeURL); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.DataEntryUrlBox.size = swap; + swap = bytereverse('url '); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.DataEntryUrlBox.type = swap; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.DataEntryUrlBox.flags = swap; // =1 Track in same file as movie atom. + + //Data Reference + sizeDREF = sizeURL+ 16; + swap = bytereverse(sizeDREF); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.size = swap; + swap = bytereverse('dref'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.flags = 0; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox. + DataReferenceBox.entry_count = swap; + + //Data information Box// + sizeDINF = sizeDREF + 8; + swap = bytereverse(sizeDINF); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.size = swap; + swap = bytereverse('dinf'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.type = swap; + + + //Null Media Header Box + swap = bytereverse(12); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.NullMediaHeaderBox.size = swap ; + swap = bytereverse ('nmhd'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.NullMediaHeaderBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.NullMediaHeaderBox.flags = 0; + + //Media Information Box// + sizeMINF = sizeDINF + sizeSTBL + 8 + 12; + swap = bytereverse(sizeMINF); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.size = swap; + swap = bytereverse('minf'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.type = swap; + + //Handler Box// + sizeHDLR = 37; + swap = bytereverse(sizeHDLR); + moov->TrackBox[numtrack].MediaBox.HandlerBox.size = swap; + swap = bytereverse('hdlr'); + moov->TrackBox[numtrack].MediaBox.HandlerBox.type = swap; + moov->TrackBox[numtrack].MediaBox.HandlerBox.version = 0; + moov->TrackBox[numtrack].MediaBox.HandlerBox.pre_defined = 0; + swap = bytereverse('text'); + moov->TrackBox[numtrack].MediaBox.HandlerBox.handler_type = swap; + moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[0] = 0; + moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[1] = 0; + moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[2] = 0; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[0] = 't'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[1] = 'e'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[2] = 'x'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[3] = 't'; + moov->TrackBox[numtrack].MediaBox.HandlerBox.data[4] = '\0'; + + //Media Header Box// + sizeMDHD = 32; + swap = bytereverse(sizeMDHD); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.size = swap; + swap = bytereverse('mdhd'); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.version = 0; + swap = bytereverse(clock); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.creation_time = swap; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.modification_time = swap; + swap = bytereverse(1000); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.timescale = swap; + swap = bytereverse(durationTrack); + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.duration = swap; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.language = 0xC455; + moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.pre_defined = 0; + + //Media Box// + sizeMDIA = sizeMDHD + sizeHDLR + sizeMINF + 8; + swap = bytereverse(sizeMDIA); + moov->TrackBox[numtrack].MediaBox.size = swap; + swap = bytereverse('mdia'); + moov->TrackBox[numtrack].MediaBox.type = swap; + + //Track Header// + sizeTKHD = 92; + swap = bytereverse (sizeTKHD); + moov->TrackBox[numtrack].TrackHeaderBox.size = swap; + swap = bytereverse ('tkhd'); + moov->TrackBox[numtrack].TrackHeaderBox.type = swap ; + swap = bytereverse (0x00000007); + moov->TrackBox[numtrack].TrackHeaderBox.version = swap; + swap = bytereverse (clock); + moov->TrackBox[numtrack].TrackHeaderBox.creation_time = swap; + moov->TrackBox[numtrack].TrackHeaderBox.modification_time = swap; + moov->TrackBox[numtrack].TrackHeaderBox.track_ID = bytereverse(12345678); + moov->TrackBox[numtrack].TrackHeaderBox.reserved = 0; + swap = bytereverse (durationTrack); + moov->TrackBox[numtrack].TrackHeaderBox.duration = swap; + moov->TrackBox[numtrack].TrackHeaderBox.reserved2[0] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.reserved2[1] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.layer = 0; + moov->TrackBox[numtrack].TrackHeaderBox.alternate_group = 0; + moov->TrackBox[numtrack].TrackHeaderBox.volume = 0; + moov->TrackBox[numtrack].TrackHeaderBox.reserved3 = 0; + swap = bytereverse (0x00010000); + moov->TrackBox[numtrack].TrackHeaderBox.matrix[0] = swap; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[1] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[2] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[3] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[4] = swap; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[5] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[6] = 0; + moov->TrackBox[numtrack].TrackHeaderBox.matrix[7] = 0; + swap = bytereverse(0x40000000); + moov->TrackBox[numtrack].TrackHeaderBox.matrix[8] = swap; + moov->TrackBox[numtrack].TrackHeaderBox.width =0; + moov->TrackBox[numtrack].TrackHeaderBox.height = 0; + + //Track container + sizeTRAK = sizeTKHD + sizeMDIA + 8; + swap = bytereverse (sizeTRAK); // Size of one track + moov->TrackBox[numtrack].size = swap; + swap = bytereverse ('trak'); + moov->TrackBox[numtrack].type = swap; + + return sizeTRAK; +} + + +int aux (FILE *text,int num,int num1,int num2,int num3,int *sal) { + int dat=0,dat1=0,dat2=0,dat3=0,size=0,d=0,cnt=0,i=0; + fseek(text,0,SEEK_SET); + d=0; + while(d==0){ + + fread (&dat,sizeof(unsigned char),1,text); + cnt++; + fread (&dat1,sizeof(unsigned char),1,text); + cnt++; + fread (&dat2,sizeof(unsigned char),1,text); + cnt++; + fread (&dat3,sizeof(unsigned char),1,text); + cnt++; + fseek(text, -3 ,SEEK_CUR); + if(dat == num && dat1 == num1 && dat2 == num2 && dat3 == num3){ + + d=1; + } + + else{ + + cnt=cnt-3; + } + + } //end while + + + fseek (text,0,SEEK_SET);//positionate the pointer at first + + cnt=cnt-7;//size is located 7 bytes before type + for (d=1;d<=cnt;d++){ + + fread (&dat,sizeof(unsigned char),1,text); + + } + fread (&dat1,sizeof(unsigned char),1,text); + fread (&dat2,sizeof(unsigned char),1,text); + fread (&dat3,sizeof(unsigned char),1,text); + + size = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + for (i=1;i<=8;i++) { //advance sample_size + fread (&dat,sizeof(unsigned char),1,text); + } + fread(&dat,1,1,text); + fread(&dat1,1,1,text); + fread(&dat2,1,1,text); + fread(&dat3,1,1,text); + + *sal = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + + return size; + +} + +int samplecontainer_text(MovieBox *moov, int numtrack, int sizemdat,const char *textfiles,int totaltracks) { + + u32 sizeSTSD, sizeSTSZ, swap,i=0; + u32 sizeSTTS; + u32 sizeSTSC = 0; + u32 sizeSTCO = 0; + u32 sizeSTBL=0; + int dat=0,dat1=0,dat2=0,dat3=0,sal=0, samplecount=0; + + //Sample Description Box// + FILE *text; + + text=fopen ( textfiles,"rb"); + fseek(text,0,SEEK_CUR); + + //stsd + + sizeSTSD =16+64; + swap = bytereverse(sizeSTSD); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.size = swap; + swap = bytereverse('stsd'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.version = 0; + swap = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleDescriptionBox.entry_count = swap; + + + //tx3g + swap = bytereverse(64); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.size=swap; + swap = bytereverse('tx3g'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.type=swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.a=0; + swap=bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.b=swap; + swap = bytereverse(0x00000800);//continuous karaoke + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.displayFlags = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.horizontaljustification=0x01; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.verticaljustification=0x01; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.backgroundcolorrgba[0]= 0x00; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.backgroundcolorrgba[1]= 0x00; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.backgroundcolorrgba[2]= 0x00; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.backgroundcolorrgba[3]= 0xFF; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.top=0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.left=0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.bottom=0x6400; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.right=0x2C01; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.startChar=0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.endChar=0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.fontID=0x0100; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.facestyleflags=0x01; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.fontsize=0x0A; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.textcolorrgba[0]=0xFF; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.textcolorrgba[1]=0xFF; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.textcolorrgba[2]=0xFF; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.textcolorrgba[3]=0xFF; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.size =0x12000000; + swap =bytereverse('ftab'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.type =swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.entrycount=0x0100; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.fontID =0x0200; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.fontnamelenght =0x05; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.font[0] =0x53; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.font[1] =0x65; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.font[2] =0x72; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.font[3] =0x69; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.TextSampleEntry.FontTableBox.font[4] =0x66; + + //stsz + + sizeSTSZ=aux(text,0x73,0x74,0x73,0x7A,&sal)+4; // the function aux looks for the box stsz in 3gp file and returns the size + swap = bytereverse('stsz'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.version = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox.sample_size=0; + + fseek(text,0,SEEK_CUR); + + fread(&dat,1,1,text); //read sample_count + fread(&dat1,1,1,text); + fread(&dat2,1,1,text); + fread(&dat3,1,1,text); + + samplecount = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + swap= bytereverse(samplecount); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox.sample_count=swap; + + for (i=1;i<=samplecount;i++){ + + swap = bytereverse(size_phrase[i-1]); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox.entry_size[i-1]=swap; + } + + sizeSTSZ= 20 + bytereverse(moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox.sample_count)*4; + swap = bytereverse(sizeSTSZ); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleSizeBox.size = swap; + + + //Time To Sample Box// + + fseek (text,0,SEEK_SET);//positionate the pointer at first + sizeSTTS=aux(text,0x73,0x74,0x74,0x73,&sal); + + swap = bytereverse(sizeSTTS); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.size = swap; + swap = bytereverse('stts'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + TimeToSampleBox.version = 0; + swap = bytereverse(sal); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox.entry_count=swap; + fseek(text,0,SEEK_CUR); + for(i=1;i<=sal;i++){ + + fread(&dat,1,1,text);//read count + fread(&dat1,1,1,text); + fread(&dat2,1,1,text); + fread(&dat3,1,1,text); + + dat = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + + swap = bytereverse(dat); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox.sample_count[i-1]=swap; + fread(&dat,1,1,text);//read delta + + fread(&dat1,1,1,text); + + fread(&dat2,1,1,text); + + fread(&dat3,1,1,text); + + + dat = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + swap = bytereverse(dat/0.6);// the input text file has time_scale = 600 but the audio has time scale=1000 + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox.sample_delta[i-1]=swap; + } + + //Sample To Chunk// + + dat=0; + fseek (text,0,SEEK_SET);//positionate the pointer at first + sizeSTSC = aux(text,0x73,0x74,0x73,0x63,&sal); + dat=sal; + swap = bytereverse(sizeSTSC); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.size = swap; + swap = bytereverse('stsc'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.version = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + SampleToChunk.entry_count = bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleToChunk.first_chunk=bytereverse(1); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleToChunk.samples_per_chunk=moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox.sample_count; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleToChunk.sample_description_index = bytereverse(1); + + //Chunk Offset Box// + sizeSTCO=24; + swap = bytereverse(sizeSTCO); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.size = swap; + swap = bytereverse('co64'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.type = swap; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.version = 0; + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.entry_count = bytereverse(1); + dat=32+sizemdat*totaltracks; + swap=bytereverse(dat); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. + ChunkOffsetBox.chunk_offset [0]= swap; + + //Sample Table Box // + sizeSTBL = 8 + sizeSTSD + sizeSTSZ + sizeSTSC + sizeSTCO + sizeSTTS; + swap = bytereverse(sizeSTBL); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.size = swap; + swap = bytereverse('stbl'); + moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.type =swap; + return sizeSTBL; +} + +//AUX Functions for endianness + +int bytereverse(int num) { + int swapped; + swapped = ((num>>24)&0xff) | // move byte 3 to byte 0 + ((num<<8)&0xff0000) | // move byte 1 to byte 2 + ((num>>8)&0xff00) | // move byte 2 to byte 1 + ((num<<24)&0xff000000); // byte 0 to byte 3 + return swapped; +} +int bytereverse16(int num) { + int swapped; + swapped = ( ((num<<8)&0xff00) | // move byte 1 to byte 2 + ((num>>8)&0x00ff) ); // byte 2 to byte 1 + return swapped; +} diff -r 66ef06a6d591 -r e3a4831f9c64 main/IMAFencoder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/IMAFencoder.h Tue Nov 05 11:17:35 2013 +0000 @@ -0,0 +1,609 @@ +#ifndef IMAFENCODER_H +#define IMAFENCODER_H + +//***********************************************************// +// Interactive Music Audio Format (IMAF) ENCODER // +// Version 2.0 // +// // +// Eugenio Oñate Hospital // +// Costantino Taglialatela & Jesus Corral Garcìa // +// // +// Copyright (c) 2013 Centre for Digital Music (C4DM) // +// Queen Mary University of London. All rights reserved. // +//***********************************************************// +// IM_AF Encoder.h // +//***********************************************************// + + +/* for FILE typedef, */ +#include + +#define maxtracks 8 //change this value to support more than 8 audio tracks. This value was 6 before I changed it +#define maxgroups 2 +#define maxpreset 10 +#define maxrules 10 +#define maxfilters 3 //Max number of Filters for an EQ preset +#define maxdynamic 2 //Max number of Dynamic Volume changes +#define num_ch 2 //Number of channel outputs (STEREO) + +typedef long long u64; +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +//typedef struct nametrack { // Stores the different titles of the tracks +// char title[20]; +//}nametrack[maxtracks]; + +typedef struct FileTypeBox +{ + u32 size; + u32 type; // ftyp + u32 major_brand; // brand identifier + u32 minor_version; // informative integer for the mirror version + u32 compatible_brands[2]; //list of brands +}FileTypeBox; + +typedef struct MovieBox //extends Box('moov') +{ + u32 size; + u32 type; // moov + + struct MovieHeaderBox + { + u32 size; + u32 type; // mvhd + u32 version; // version + flag + u32 creation_time; + u32 modification_time; + u32 timescale; // specifies the time-scale + u32 duration; + u32 rate; // typically 1.0 + u16 volume; // typically full volume + u16 reserved; // =0 + u32 reserved2[2]; //=0 + u32 matrix[9]; // information matrix for video (u,v,w) + u32 pre_defined[6]; // =0 + u32 next_track_ID; //non zero value for the next track ID + }MovieHeaderBox; + + struct TrackBox + { + u32 size; + u32 type; + struct TrackHeaderBox + { + u32 size; + u32 type; + u32 version; // version + flag + u32 creation_time; + u32 modification_time; + u32 track_ID; + u32 reserved; // =0 + u32 duration; + u32 reserved2[2]; // =0 + u16 layer; // =0 // for video + u16 alternate_group; // =0 + u16 volume; // full volume is 1 = 0x0100 + u16 reserved3;// =0 + u32 matrix[9]; // for video + u32 width; // video + u32 height; // video + }TrackHeaderBox; + + struct MediaBox // extends Box('mdia') + { + u32 size; + u32 type; + struct MediaHeaderBox // extends FullBox('mdhd', version,0) + { + u32 size; + u32 type; + u32 version; // version + flag + u32 creation_time; + u32 modification_time; + u32 timescale; + u32 duration; + u16 language; // [pad,5x3] = 16 bits and pad = 0 + u16 pre_defined; // =0 + }MediaHeaderBox; + struct HandlerBox // extends FullBox('hdlr') + { + u32 size; + u32 type; + u32 version; // version = 0 + flag + u32 pre_defined; // =0 + u32 handler_type; // = 'soun' for audio track, text or hint + u32 reserved[3]; // =0 + unsigned char data[5]; // Does not work! only 4 bytes + + }HandlerBox; + struct MediaInformationBox //extends Box('minf') + { + u32 size; + u32 type; + // smhd in sound track only!! + struct SoundMediaHeaderBox //extends FullBox('smhd') + { + u32 size; + u32 type; + u32 version; + u16 balance; // =0 place mono tracks in stereo. 0 is center + u16 reserved; // =0 + }SoundMediaHeaderBox; + struct NullMediaHeaderBox //extends FullBox('nmhd') + { + u32 size; + u32 type; + u32 flags; + }NullMediaHeaderBox; + struct DataInformationBox //extends Box('dinf') + { + u32 size; + u32 type; + struct DataReferenceBox + { + u32 size; + u32 type; + u32 flags; + u32 entry_count; // counts the actual entries. + struct DataEntryUrlBox //extends FullBox('url', version=0, flags) + { + u32 size; + u32 type; + u32 flags; + }DataEntryUrlBox; + }DataReferenceBox; + }DataInformationBox; + struct SampleTableBox // extends Box('stbl') + { + u32 size; + u32 type; + struct TimeToSampleBox{ + u32 size; + u32 type; + u32 version; + u32 entry_count; + u32 sample_count[3000]; + u32 sample_delta[3000]; + }TimeToSampleBox; + struct SampleDescriptionBox // stsd + { + u32 size; + u32 type; + u32 version; + u32 entry_count; // = 1 number of entries + // unsigned char esds[88]; + struct TextSampleEntry{ + u32 size; + u32 type; //tx3g + u32 a; + u32 b; + u32 displayFlags; + u8 horizontaljustification; + u8 verticaljustification; + u8 backgroundcolorrgba[4]; + u16 top; + u16 left; + u16 bottom; + u16 right; + //StyleRecord + u16 startChar; + u16 endChar; + u16 fontID; + u8 facestyleflags; + u8 fontsize; + u8 textcolorrgba[4]; + struct FontTableBoX{ + u32 size; + u32 type; + u16 entrycount; + u16 fontID; + u8 fontnamelenght; + u8 font[5]; //Serif + }FontTableBox; + }TextSampleEntry; + struct AudioSampleEntry{ + u32 size; + u32 type; //mp4a + char reserved[6]; + u16 data_reference_index; // = 1 + u32 reserved2[2]; + u16 channelcount; // = 2 + u16 samplesize; // = 16 + u32 reserved3; + u32 samplerate; // 44100 << 16 + // unsigned char esds[81]; + struct ESbox{ + u32 size; + u32 type; + u32 version; + struct ES_Descriptor{ + unsigned char tag; + unsigned char length; + u16 ES_ID; + unsigned char mix; + struct DecoderConfigDescriptor{ + unsigned char tag; + unsigned char length; + unsigned char objectProfileInd; + u32 mix; + u32 maxBitRate; + u32 avgBitrate; + /* struct DecoderSpecificInfo{ + unsigned char tag; + unsigned length; + // unsigned char decSpecificInfosize; + unsigned char decSpecificInfoData[2]; + }DecoderSpecificInfo; + */ }DecoderConfigDescriptor; + struct SLConfigDescriptor{ + unsigned char tag; + unsigned char length; + unsigned char predifined; + }SLConfigDescriptor; + }ES_Descriptor; + }ESbox; + }AudioSampleEntry; + }SampleDescriptionBox; + struct SampleSizeBox{ + u32 size; + u32 type; + u32 version; + u32 sample_size; // =0 + u32 sample_count; + u32 entry_size[9000]; + }SampleSizeBox; + struct SampleToChunk{ + u32 size; + u32 type; + u32 version; + u32 entry_count; + u32 first_chunk; + u32 samples_per_chunk; + u32 sample_description_index; + }SampleToChunk; + struct ChunkOffsetBox{ + u32 size; + u32 type; + u32 version; + u32 entry_count; + u32 chunk_offset[maxtracks]; + }ChunkOffsetBox; + }SampleTableBox; + }MediaInformationBox; + }MediaBox; + }TrackBox[maxtracks]; // max 10 tracks + + struct PresetContainerBox // extends Box('prco') + { + u32 size; + u32 type; + unsigned char num_preset; + unsigned char default_preset_ID; + struct PresetBox //extends FullBox('prst',version=0,flags) + { + u32 size; + u32 type; + u32 flags; + unsigned char preset_ID; + unsigned char num_preset_elements; + struct presElemId{ + u32 preset_element_ID; + }presElemId[maxtracks]; + unsigned char preset_type; + unsigned char preset_global_volume; + + // if (preset_type == 0) || (preset_type == 8) - Static track volume preset + struct StaticTrackVolume{ + struct presVolumElem{ + u8 preset_volume_element; + struct EQ{ // if preset_type == 8 (with EQ) + u8 num_eq_filters; + struct Filter{ + u8 filter_type; + u16 filter_reference_frequency; + u8 filter_gain; + u8 filter_bandwidth; + }Filter[maxfilters]; + }EQ; + }presVolumElem[maxtracks]; + }StaticTrackVolume; + + // if (preset_type == 1) || (preset_type == 9) - Static object volume preset + struct StaticObjectVolume{ + struct InputCH{ + u8 num_input_channel; + }InputCH[maxtracks]; + u8 output_channel_type; + struct presElVol_1{ + struct Input{ + struct Output{ + u8 preset_volume_element; + }Output[num_ch]; + struct EQ_1{ // if preset_type == 9 (with EQ) + u8 num_eq_filters; + struct Filter_1{ + u8 filter_type; + u16 filter_reference_frequency; + u8 filter_gain; + u8 filter_bandwidth; + }Filter[maxfilters]; + }EQ; + }Input[num_ch]; + }presElVol[maxtracks]; + }StaticObjectVolume; + + // if (preset_type == 2) || (preset_type == 10) - Dynamic track volume preset + struct DynamicTrackVolume{ + u16 num_updates; + struct DynamicChange{ + u16 updated_sample_number; + struct presVolumElem_2{ + u8 preset_volume_element; + struct EQ_2{ // if preset_type == 10 (with EQ) + u8 num_eq_filters; + struct Filter_2{ + u8 filter_type; + u16 filter_reference_frequency; + u8 filter_gain; + u8 filter_bandwidth; + }Filter[maxfilters]; + }EQ; + }presVolumElem[maxtracks]; + }DynamicChange[maxdynamic]; + }DynamicTrackVolume; + + // if (preset_type == 3) || (preset_type == 11) - Dynamic object volume preset + struct DynamicObjectVolume{ + u16 num_updates; + struct InputCH_3{ + u8 num_input_channel; + }InputCH[maxtracks]; + u8 output_channel_type; + struct DynamicChange_3{ + u16 updated_sample_number; + struct presElVol{ + struct Input_3{ + struct Output_3{ + u8 preset_volume_element; + }Output[num_ch]; + struct EQ_3{ // if preset_type == 11 (with EQ) + u8 num_eq_filters; + struct Filter_3{ + u8 filter_type; + u16 filter_reference_frequency; + u8 filter_gain; + u8 filter_bandwidth; + }Filter[maxfilters]; + }EQ; + }Input[num_ch]; + }presElVol[maxtracks]; + }DynamicChange[maxdynamic]; + }DynamicObjectVolume; + + // if (preset_type == 4) || (preset_type == 12) - Dynamic track approximated volume preset + struct DynamicTrackApproxVolume{ + u16 num_updates; + struct DynamicChange_4{ + u16 start_sample_number; + u16 duration_update; + struct presElVol_4{ + u8 end_preset_volume_element; + struct EQ_4{ // if preset_type == 12 (with EQ) + u8 num_eq_filters; + struct Filter_4{ + u8 filter_type; + u16 filter_reference_frequency; + u8 end_filter_gain; + u8 filter_bandwidth; + }Filter[maxfilters]; + }EQ; + }presElVol[maxtracks]; + }DynamicChange[maxdynamic]; + }DynamicTrackApproxVolume; + + // if (preset_type == 5) || (preset_type == 13) - Dynamic object approximated volume preset + // THIS STRUCTURE GIVES STACK OVERFLOW PROBLEMS - MORE STACK SIZE NEEDED -> Needs investigation + struct DynamicObjectApproxVolume{ + u16 num_updates; + struct InputCH_5{ + u8 num_input_channel; + }InputCH[maxtracks]; + u8 output_channel_type; + struct DynamicChange_5{ + u16 start_sample_number; + u16 duration_update; + struct presElVol_5{ + struct Input_5{ + struct Output_5{ + u8 preset_volume_element; + }Output[num_ch]; + struct EQ_5{ // if preset_type == 11 (with EQ) + u8 num_eq_filters; + struct Filter_5{ + u8 filter_type; + u16 filter_reference_frequency; + u8 end_filter_gain; + u8 filter_bandwidth; + }Filter[maxfilters]; + }EQ; + }Input[num_ch]; + }presElVol[maxtracks]; + }DynamicChange[maxdynamic]; + }DynamicObjectApproxVolume; + + char preset_name[50]; + + }PresetBox[maxpreset]; + + }PresetContainerBox; + + struct RulesContainer{ + u32 size; + u32 type; + u16 num_selection_rules; + u16 num_mixing_rules; + struct SelectionRules{ + u32 size; + u32 type; + u32 version; + u16 selection_rule_ID; + unsigned char selection_rule_type; + u32 element_ID; + // Only for Min/Max Rule + // if (selection_rule_type==0) + u16 min_num_elements; + u16 max_num_elements; + // Only for Exclusion and Implication Rules + // if (selection_rule_type==1 || selection_rule_type==3) + u32 key_element_ID; + char rule_description[20]; + }SelectionRules; + struct MixingRules{ + u32 size; + u32 type; + u32 version; + u16 mixing_rule_ID; + unsigned char mixing_type; + u32 element_ID; + u16 min_volume; + u16 max_volume; + u32 key_elem_ID; + char mix_description[17]; + }MixingRules; + }RulesContainer; + struct GroupContainerBox{ //extends Box('grco') + u32 size; // = 10 + sizeGRUP + u32 type; + u16 num_groups; + struct GroupBox{ // extends FullBox('grup') + u32 size; // = 21 + 22 + 32 (+2 if group_activation_mode = 2) + u32 type; + u32 version; + u32 group_ID; + u16 num_elements; + struct groupElemId{ + u32 element_ID; + }groupElemId[maxtracks]; + unsigned char group_activation_mode; + u16 group_activation_elements_number; + u16 group_reference_volume; + char group_name[22]; + char group_description[32]; + }GroupBox[maxgroups]; + }GroupContainerBox; +}MovieBox; + +typedef struct MetaBox // extends FullBox ('meta') +{ + u32 size; + u32 type; + u32 version; + struct theHandler //extends FullBox HandlerBox('hdlr') + { + u32 size; + u32 type; + u32 version; // version = 0 + flag + u32 pre_defined; // =0 + u32 handler_type; // = 'meta' for Timed Metadata track + u32 reserved[3]; // =0 + unsigned char name[4]; + }theHandler; + struct file_locations //extends Box DataInformationBox('dinf') + { + u32 size; + u32 type; +/* struct DataReferenceBox2 + { + u32 size; + u32 type; + u32 flags; + u32 entry_count; // = 1 + struct DataEntryUrlBox2 //extends FullBox('url', version=0, flags) + { + u32 size; + u32 type; + u32 flags; + }DataEntryUrlBox; + }DataReferenceBox; */ + }file_locations; + struct item_locations //extends FullBox ItemLocationBox('iloc') + { + u32 size; + u32 type; + u32 version; // version = 0 + flags + unsigned char offset_size; // = 4 bytes + unsigned char lenght_size; // = 4 bytes + unsigned char base_offset_size; // = 4 bytes + unsigned char reserved; // = 0 + u16 item_count; // = 1 + u16 item_ID; // = 1 + u16 data_reference_index; // = 0 (this file) + u32 base_offset; // size=(base_offset_size*8)=4*8 + u16 extent_count; // = 1 + u32 extent_offset; // size=(offset_size*8)=4*8 + u32 extent_length; // size=(lenght_size*8)=4*8 + }item_locations; + struct item_infos //extends FullBox ItemInfoBox('iinf') + { + u32 size; + u32 type; + u32 version; // version = 0 + flag + u16 entry_count; // = 1 + struct info_entry// extends FullBox ItemInfoEntry('infe') + { + u32 size; + u32 type; + u32 version; // = 0 + u16 item_ID; // = 1 + u16 item_protection_index; // = 0 for "unprotected" + char item_name[6]; // name with max 5 characters + char content_type[18]; // = 'application/other' -> 17 characters + char content_encoding[4]; // = 'jpg' for JPEG image -> 3 characters + }info_entry; + }item_infos; + struct XMLBox // extends FullBox('xml ') + { + u32 size; + u32 type; + u32 version; + char string[2000]; + }XMLBox; +}MetaBox; + +typedef struct MediaDataBox // extends Box('mdat') +{ + u32 size; + u32 type; + unsigned char data; +}MediaDataBox; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif // IMAFENCODER_H diff -r 66ef06a6d591 -r e3a4831f9c64 main/MainWindow.cpp --- a/main/MainWindow.cpp Tue Nov 05 11:14:16 2013 +0000 +++ b/main/MainWindow.cpp Tue Nov 05 11:17:35 2013 +0000 @@ -5,7 +5,7 @@ An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2006-2007 Chris Cannam and QMUL. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the @@ -13,6 +13,7 @@ COPYING included with this distribution for more information. */ + #include "../version.h" #include "MainWindow.h" @@ -127,6 +128,24 @@ using std::map; using std::set; +//IMAF REQUIRED LIBRARIES AND VARIABLES +#include "IMAFencoder.c" +#include "checkbox.h" +#include +#include "imafdecoder.cpp" + +QString ImafFileName,ImageFileName,TextFileName; //name of the files +QString files_paths[maxtracks]; // change maxtracks in IMAFencoder.h +int ImafVolumeValues[maxtracks]; +int numtracks; +bool has_image, has_lyrics; +int selrule_type, selrule_par1, selrule_par2; +int mixrule_type, mixrule_par1, mixrule_par2, mixrule_par3, mixrule_par4; +int group_tracks[maxtracks], group_volume; +QString group_descr, group_name; +int preset_type, fade_in; + +bool isIMAF; MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) : MainWindowBase(withAudioOutput, withOSCSupport, true), @@ -244,7 +263,7 @@ m_playSpeed->setRangeMapper(new PlaySpeedRangeMapper(0, 200)); m_playSpeed->setShowToolTip(true); connect(m_playSpeed, SIGNAL(valueChanged(int)), - this, SLOT(playSpeedChanged(int))); + this, SLOT(playSpeedChanged(int))); connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); @@ -263,7 +282,7 @@ layout->addWidget(m_playSpeed, 1, 3); layout->addWidget(m_fader, 1, 4); - m_playControlsWidth = + m_playControlsWidth = m_fader->width() + m_playSpeed->width() + layout->spacing() * 2; layout->setColumnMinimumWidth(0, 14); @@ -303,12 +322,12 @@ connect(m_midiInput, SIGNAL(eventsAvailable()), this, SLOT(midiEventsAvailable())); - + TransformFactory::getInstance()->startPopulationThread(); - m_versionTester = new VersionTester + VersionTester *vt = new VersionTester ("sonicvisualiser.org", "/latest-version.txt", SV_VERSION); - connect(m_versionTester, SIGNAL(newerVersionAvailable(QString)), + connect(vt, SIGNAL(newerVersionAvailable(QString)), this, SLOT(newerVersionAvailable(QString))); } @@ -319,7 +338,6 @@ delete m_activityLog; delete m_preferencesDialog; delete m_layerTreeDialog; - delete m_versionTester; Profiles::getInstance()->dump(); // SVDEBUG << "MainWindow::~MainWindow finishing" << endl; } @@ -491,7 +509,7 @@ m_keyReference->registerShortcut(action); menu->addAction(action); toolbar->addAction(action); - + icon = il.load("filesaveas"); icon.addPixmap(il.loadPixmap("filesaveas-22")); action = new QAction(icon, tr("Save Session &As..."), this); @@ -531,6 +549,16 @@ connect(this, SIGNAL(canExportAudio(bool)), action, SLOT(setEnabled(bool))); menu->addAction(action); + QAction *actionCreateIMAF = new QAction(tr("&Export IMAF File..."), this); + actionCreateIMAF->setStatusTip(tr("Export selection as an IMAF file")); + menu->addAction(actionCreateIMAF); + connect(actionCreateIMAF,SIGNAL(triggered()),this,SLOT(exportIMAF())); + + QAction *actionOpenIMAF = new QAction(tr("&Import IMAF File..."), this); + actionOpenIMAF->setStatusTip(tr("Import IMAF file")); + menu->addAction(actionOpenIMAF); + connect(actionOpenIMAF,SIGNAL(triggered()),this,SLOT(importIMAF())); + menu->addSeparator(); action = new QAction(tr("Import Annotation &Layer..."), this); @@ -583,7 +611,7 @@ action->setStatusTip(tr("Adjust the application preferences")); connect(action, SIGNAL(triggered()), this, SLOT(preferences())); menu->addAction(action); - + menu->addSeparator(); action = new QAction(il.load("exit"), tr("&Quit"), this); @@ -670,7 +698,7 @@ m_keyReference->registerShortcut(action); menu->addAction(action); m_rightButtonMenu->addAction(action); - + action = new QAction(tr("Select &Visible Range"), this); action->setShortcut(tr("Ctrl+Shift+A")); action->setStatusTip(tr("Select the time range corresponding to the current window width")); @@ -678,7 +706,7 @@ connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(action); menu->addAction(action); - + action = new QAction(tr("Select to &Start"), this); action->setShortcut(tr("Shift+Left")); action->setStatusTip(tr("Select from the start of the session to the current playback position")); @@ -686,7 +714,7 @@ connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(action); menu->addAction(action); - + action = new QAction(tr("Select to &End"), this); action->setShortcut(tr("Shift+Right")); action->setStatusTip(tr("Select from the current playback position to the end of the session")); @@ -791,7 +819,7 @@ action->setStatusTip(tr("Set the counters used for counter-based labelling")); connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounters())); menu->addAction(action); - + action = new QAction(tr("Renumber Selected Instants"), this); action->setStatusTip(tr("Renumber the selected instants using the current labelling scheme")); connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants())); @@ -820,7 +848,7 @@ connect(this, SIGNAL(canScroll(bool)), m_scrollLeftAction, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(m_scrollLeftAction); menu->addAction(m_scrollLeftAction); - + m_scrollRightAction = new QAction(tr("Scroll &Right"), this); m_scrollRightAction->setShortcut(tr("Right")); m_scrollRightAction->setStatusTip(tr("Scroll the current pane to the right")); @@ -828,7 +856,7 @@ connect(this, SIGNAL(canScroll(bool)), m_scrollRightAction, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(m_scrollRightAction); menu->addAction(m_scrollRightAction); - + action = new QAction(tr("&Jump Left"), this); action->setShortcut(tr("Ctrl+Left")); action->setStatusTip(tr("Scroll the current pane a big step to the left")); @@ -836,7 +864,7 @@ connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(action); menu->addAction(action); - + action = new QAction(tr("J&ump Right"), this); action->setShortcut(tr("Ctrl+Right")); action->setStatusTip(tr("Scroll the current pane a big step to the right")); @@ -852,7 +880,7 @@ connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(action); menu->addAction(action); - + action = new QAction(tr("Peek Right"), this); action->setShortcut(tr("Alt+Right")); action->setStatusTip(tr("Scroll the current pane to the right without moving the playback cursor or other panes")); @@ -873,7 +901,7 @@ connect(this, SIGNAL(canZoom(bool)), m_zoomInAction, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(m_zoomInAction); menu->addAction(m_zoomInAction); - + m_zoomOutAction = new QAction(il.load("zoom-out"), tr("Zoom &Out"), this); m_zoomOutAction->setShortcut(tr("Down")); @@ -882,7 +910,7 @@ connect(this, SIGNAL(canZoom(bool)), m_zoomOutAction, SLOT(setEnabled(bool))); m_keyReference->registerShortcut(m_zoomOutAction); menu->addAction(m_zoomOutAction); - + action = new QAction(tr("Restore &Default Zoom"), this); action->setStatusTip(tr("Restore the zoom level to the default")); connect(action, SIGNAL(triggered()), this, SLOT(zoomDefault())); @@ -921,7 +949,7 @@ menu->addSeparator(); QActionGroup *overlayGroup = new QActionGroup(this); - + action = new QAction(tr("Show &No Overlays"), this); action->setShortcut(tr("0")); action->setStatusTip(tr("Hide times, layer names, and scale")); @@ -931,7 +959,7 @@ overlayGroup->addAction(action); m_keyReference->registerShortcut(action); menu->addAction(action); - + action = new QAction(tr("Show &Minimal Overlays"), this); action->setShortcut(tr("9")); action->setStatusTip(tr("Show times and basic scale")); @@ -941,7 +969,7 @@ overlayGroup->addAction(action); m_keyReference->registerShortcut(action); menu->addAction(action); - + action = new QAction(tr("Show &All Overlays"), this); action->setShortcut(tr("8")); action->setStatusTip(tr("Show times, layer names, and scale")); @@ -953,7 +981,7 @@ menu->addAction(action); menu->addSeparator(); - + action = new QAction(tr("Show &Zoom Wheels"), this); action->setShortcut(tr("Z")); action->setStatusTip(tr("Show thumbwheels for zooming horizontally and vertically")); @@ -1016,18 +1044,18 @@ MainWindow::setupPaneAndLayerMenus() { if (m_paneMenu) { - m_paneActions.clear(); - m_paneMenu->clear(); + m_paneActions.clear(); + m_paneMenu->clear(); } else { - m_paneMenu = menuBar()->addMenu(tr("&Pane")); + m_paneMenu = menuBar()->addMenu(tr("&Pane")); m_paneMenu->setTearOffEnabled(true); } if (m_layerMenu) { - m_layerActions.clear(); - m_layerMenu->clear(); + m_layerActions.clear(); + m_layerMenu->clear(); } else { - m_layerMenu = menuBar()->addMenu(tr("&Layer")); + m_layerMenu = menuBar()->addMenu(tr("&Layer")); m_layerMenu->setTearOffEnabled(true); } @@ -1061,44 +1089,43 @@ // menu->addSeparator(); LayerFactory::LayerTypeSet emptyLayerTypes = - LayerFactory::getInstance()->getValidEmptyLayerTypes(); + LayerFactory::getInstance()->getValidEmptyLayerTypes(); for (LayerFactory::LayerTypeSet::iterator i = emptyLayerTypes.begin(); - i != emptyLayerTypes.end(); ++i) { - - QIcon icon; - QString mainText, tipText, channelText; - LayerFactory::LayerType type = *i; - QString name = LayerFactory::getInstance()->getLayerPresentationName(type); - - icon = il.load(LayerFactory::getInstance()->getLayerIconName(type)); - - mainText = tr("Add New %1 Layer").arg(name); - tipText = tr("Add a new empty layer of type %1").arg(name); - - action = new QAction(icon, mainText, this); - action->setStatusTip(tipText); - - if (type == LayerFactory::Text) { - action->setShortcut(tr("T")); + i != emptyLayerTypes.end(); ++i) { + + QIcon icon; + QString mainText, tipText, channelText; + LayerFactory::LayerType type = *i; + QString name = LayerFactory::getInstance()->getLayerPresentationName(type); + + icon = il.load(LayerFactory::getInstance()->getLayerIconName(type)); + + mainText = tr("Add New %1 Layer").arg(name); + tipText = tr("Add a new empty layer of type %1").arg(name); + + action = new QAction(icon, mainText, this); + action->setStatusTip(tipText); + + if (type == LayerFactory::Text) { + action->setShortcut(tr("T")); m_keyReference->registerShortcut(action); - } - - connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); - connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); - m_layerActions[action] = LayerConfiguration(type); - menu->addAction(action); - m_rightButtonLayerMenu->addAction(action); } - + connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); + connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); + m_layerActions[action] = LayerConfiguration(type); + menu->addAction(action); + m_rightButtonLayerMenu->addAction(action); + } + m_rightButtonLayerMenu->addSeparator(); menu->addSeparator(); LayerFactory::LayerType backgroundTypes[] = { - LayerFactory::Waveform, - LayerFactory::Spectrogram, - LayerFactory::MelodicRangeSpectrogram, - LayerFactory::PeakFrequencySpectrogram, + LayerFactory::Waveform, + LayerFactory::Spectrogram, + LayerFactory::MelodicRangeSpectrogram, + LayerFactory::PeakFrequencySpectrogram, LayerFactory::Spectrum }; @@ -1110,24 +1137,24 @@ } for (unsigned int i = 0; - i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) { + i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) { const int paneMenuType = 0, layerMenuType = 1; - for (int menuType = paneMenuType; menuType <= layerMenuType; ++menuType) { - - if (menuType == paneMenuType) menu = m_paneMenu; - else menu = m_layerMenu; - - QMenu *submenu = 0; + for (int menuType = paneMenuType; menuType <= layerMenuType; ++menuType) { + + if (menuType == paneMenuType) menu = m_paneMenu; + else menu = m_layerMenu; + + QMenu *submenu = 0; QIcon icon; QString mainText, shortcutText, tipText, channelText; LayerFactory::LayerType type = backgroundTypes[i]; bool mono = true; - + switch (type) { - + case LayerFactory::Waveform: icon = il.load("waveform"); mainText = tr("Add &Waveform"); @@ -1140,7 +1167,7 @@ } mono = false; break; - + case LayerFactory::Spectrogram: icon = il.load("spectrogram"); mainText = tr("Add Spectro&gram"); @@ -1152,7 +1179,7 @@ tipText = tr("Add a new layer showing a spectrogram"); } break; - + case LayerFactory::MelodicRangeSpectrogram: icon = il.load("spectrogram"); mainText = tr("Add &Melodic Range Spectrogram"); @@ -1164,7 +1191,7 @@ tipText = tr("Add a new layer showing a spectrogram set up for an overview of note pitches"); } break; - + case LayerFactory::PeakFrequencySpectrogram: icon = il.load("spectrogram"); mainText = tr("Add Pea&k Frequency Spectrogram"); @@ -1176,7 +1203,7 @@ tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies"); } break; - + case LayerFactory::Spectrum: icon = il.load("spectrum"); mainText = tr("Add Spectr&um"); @@ -1188,16 +1215,16 @@ tipText = tr("Add a new layer showing a frequency spectrum"); } break; - + default: break; } std::vector candidateModels = models; - + for (std::vector::iterator mi = candidateModels.begin(); mi != candidateModels.end(); ++mi) { - + Model *model = *mi; int channels = 0; @@ -1242,9 +1269,9 @@ m_keyReference->registerShortcut(action); } menu->addAction(action); - + } else { - + if (!submenu) { submenu = menu->addMenu(mainText); submenu->setTearOffEnabled(true); @@ -1272,7 +1299,7 @@ if (isDefault) { action = new QAction(icon, actionText, this); if (!model || model == getMainModel()) { - action->setShortcut(shortcutText); + action->setShortcut(shortcutText); } } else { action = new QAction(actionText, this); @@ -1313,9 +1340,9 @@ m_layerActions[action] = LayerConfiguration(type, 0, 0); m_rightButtonLayerMenu->addAction(action); } - } - } - } + } + } + } } m_rightButtonLayerMenu->addSeparator(); @@ -1429,7 +1456,7 @@ m_transformActionsReverse.clear(); m_transformsMenu->clear(); } else { - m_transformsMenu = menuBar()->addMenu(tr("&Transform")); + m_transformsMenu = menuBar()->addMenu(tr("&Transform")); m_transformsMenu->setTearOffEnabled(true); m_transformsMenu->setSeparatorsCollapsible(true); } @@ -1455,7 +1482,7 @@ m_transformsMenu->addSeparator(); m_rightButtonTransformsMenu->addSeparator(); - + for (vector::iterator i = types.begin(); i != types.end(); ++i) { @@ -1557,9 +1584,9 @@ } for (unsigned int i = 0; i < transforms.size(); ++i) { - - QString name = transforms[i].name; - if (name == "") name = transforms[i].identifier; + + QString name = transforms[i].name; + if (name == "") name = transforms[i].identifier; // std::cerr << "Plugin Name: " << name << std::endl; @@ -1586,11 +1613,11 @@ .arg(output); } - QAction *action = new QAction(tr("%1...").arg(name), this); - connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); - m_transformActions[action] = transforms[i].identifier; + QAction *action = new QAction(tr("%1...").arg(name), this); + connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); + m_transformActions[action] = transforms[i].identifier; m_transformActionsReverse[transforms[i].identifier] = action; - connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); + connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); action->setStatusTip(transforms[i].longDescription); @@ -1629,7 +1656,7 @@ if (output == "") { parentMenu->addAction(pluginName, action); } else { - pluginNameMenus[type][pluginName] = + pluginNameMenus[type][pluginName] = parentMenu->addMenu(pluginName); connect(this, SIGNAL(canAddLayer(bool)), pluginNameMenus[type][pluginName], @@ -1668,7 +1695,7 @@ { QMenu *menu = menuBar()->addMenu(tr("&Help")); menu->setTearOffEnabled(true); - + m_keyReference->setCategory(tr("Help")); IconLoader il; @@ -1676,9 +1703,9 @@ QString name = QApplication::applicationName(); QAction *action = new QAction(il.load("help"), - tr("&Help Reference"), this); + tr("&Help Reference"), this); action->setShortcut(tr("F1")); - action->setStatusTip(tr("Open the %1 reference manual").arg(name)); + action->setStatusTip(tr("Open the %1 reference manual").arg(name)); connect(action, SIGNAL(triggered()), this, SLOT(help())); m_keyReference->registerShortcut(action); menu->addAction(action); @@ -1689,14 +1716,14 @@ connect(action, SIGNAL(triggered()), this, SLOT(keyReference())); m_keyReference->registerShortcut(action); menu->addAction(action); - - action = new QAction(tr("%1 on the &Web").arg(name), this); - action->setStatusTip(tr("Open the %1 website").arg(name)); + + action = new QAction(tr("%1 on the &Web").arg(name), this); + action->setStatusTip(tr("Open the %1 website").arg(name)); connect(action, SIGNAL(triggered()), this, SLOT(website())); menu->addAction(action); - - action = new QAction(tr("&About %1").arg(name), this); - action->setStatusTip(tr("Show information about %1").arg(name)); + + action = new QAction(tr("&About %1").arg(name), this); + action->setStatusTip(tr("Show information about %1").arg(name)); connect(action, SIGNAL(triggered()), this, SLOT(about())); menu->addAction(action); } @@ -1707,8 +1734,8 @@ m_recentFilesMenu->clear(); vector files = m_recentFiles.getRecent(); for (size_t i = 0; i < files.size(); ++i) { - QAction *action = new QAction(files[i], this); - connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile())); + QAction *action = new QAction(files[i], this); + connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile())); if (i == 0) { action->setShortcut(tr("Ctrl+R")); m_keyReference->registerShortcut @@ -1716,7 +1743,7 @@ action->shortcut().toString(), tr("Re-open the current or most recently opened file")); } - m_recentFilesMenu->addAction(action); + m_recentFilesMenu->addAction(action); } } @@ -1794,7 +1821,7 @@ } else { ti->second->setShortcut(QString("")); } - m_recentTransformsMenu->addAction(ti->second); + m_recentTransformsMenu->addAction(ti->second); } } @@ -1821,49 +1848,49 @@ for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { - Pane *pane = m_paneStack->getPane(i); - if (!pane) continue; - - for (int j = 0; j < pane->getLayerCount(); ++j) { - - Layer *layer = pane->getLayer(j); - if (!layer) continue; - if (observedLayers.find(layer) != observedLayers.end()) { + Pane *pane = m_paneStack->getPane(i); + if (!pane) continue; + + for (int j = 0; j < pane->getLayerCount(); ++j) { + + Layer *layer = pane->getLayer(j); + if (!layer) continue; + if (observedLayers.find(layer) != observedLayers.end()) { // std::cerr << "found duplicate layer " << layer << std::endl; - continue; - } - -// std::cerr << "found new layer " << layer << " (name = " + continue; + } + +// std::cerr << "found new layer " << layer << " (name = " // << layer->getLayerPresentationName() << ")" << std::endl; - orderedLayers.push_back(layer); - observedLayers.insert(layer); + orderedLayers.push_back(layer); + observedLayers.insert(layer); if (factory->isLayerSliceable(layer)) { sliceableLayers.insert(layer); } - } } + } map observedNames; for (size_t i = 0; i < orderedLayers.size(); ++i) { - + Layer *layer = orderedLayers[i]; - QString name = layer->getLayerPresentationName(); - int n = ++observedNames[name]; - if (n > 1) name = QString("%1 <%2>").arg(name).arg(n); - - QIcon icon = il.load(factory->getLayerIconName + QString name = layer->getLayerPresentationName(); + int n = ++observedNames[name]; + if (n > 1) name = QString("%1 <%2>").arg(name).arg(n); + + QIcon icon = il.load(factory->getLayerIconName (factory->getLayerType(layer))); - QAction *action = new QAction(icon, name, this); - connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); - connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); - m_existingLayerActions[action] = layer; - - m_existingLayersMenu->addAction(action); + QAction *action = new QAction(icon, name, this); + connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); + connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); + m_existingLayerActions[action] = layer; + + m_existingLayersMenu->addAction(action); if (sliceableLayers.find(layer) != sliceableLayers.end()) { action = new QAction(icon, name, this); @@ -1917,7 +1944,7 @@ m_playAction->setStatusTip(tr("Start or stop playback from the current position")); connect(m_playAction, SIGNAL(triggered()), this, SLOT(play())); connect(m_playSource, SIGNAL(playStatusChanged(bool)), - m_playAction, SLOT(setChecked(bool))); + m_playAction, SLOT(setChecked(bool))); connect(m_playSource, SIGNAL(playStatusChanged(bool)), this, SLOT(playStatusChanged(bool))); connect(this, SIGNAL(canPlay(bool)), m_playAction, SLOT(setEnabled(bool))); @@ -2037,7 +2064,7 @@ fastAction->setStatusTip(tr("Time-stretch playback to speed it up without changing pitch")); connect(fastAction, SIGNAL(triggered()), this, SLOT(speedUpPlayback())); connect(this, SIGNAL(canSpeedUpPlayback(bool)), fastAction, SLOT(setEnabled(bool))); - + QAction *slowAction = menu->addAction(tr("Slow Down")); slowAction->setShortcut(tr("Ctrl+PgDown")); slowAction->setStatusTip(tr("Time-stretch playback to slow it down without changing pitch")); @@ -2079,7 +2106,7 @@ m_toolActions[ViewManager::NavigateMode] = action; action = toolbar->addAction(il.load("select"), - tr("Select")); + tr("Select")); action->setCheckable(true); action->setShortcut(tr("2")); action->setStatusTip(tr("Select ranges")); @@ -2089,7 +2116,7 @@ m_toolActions[ViewManager::SelectMode] = action; action = toolbar->addAction(il.load("move"), - tr("Edit")); + tr("Edit")); action->setCheckable(true); action->setShortcut(tr("3")); action->setStatusTip(tr("Edit items in layer")); @@ -2100,7 +2127,7 @@ m_toolActions[ViewManager::EditMode] = action; action = toolbar->addAction(il.load("draw"), - tr("Draw")); + tr("Draw")); action->setCheckable(true); action->setShortcut(tr("4")); action->setStatusTip(tr("Draw new items in layer")); @@ -2111,7 +2138,7 @@ m_toolActions[ViewManager::DrawMode] = action; action = toolbar->addAction(il.load("erase"), - tr("Erase")); + tr("Erase")); action->setCheckable(true); action->setShortcut(tr("5")); action->setStatusTip(tr("Erase items from layer")); @@ -2167,20 +2194,20 @@ (haveCurrentPane && (currentLayer != 0)); bool havePlayTarget = - (m_playTarget != 0); - bool haveSelection = - (m_viewManager && - !m_viewManager->getSelections().empty()); + (m_playTarget != 0); + bool haveSelection = + (m_viewManager && + !m_viewManager->getSelections().empty()); bool haveCurrentEditableLayer = - (haveCurrentLayer && - currentLayer->isLayerEditable()); - bool haveCurrentTimeInstantsLayer = - (haveCurrentLayer && - dynamic_cast(currentLayer)); - bool haveCurrentTimeValueLayer = - (haveCurrentLayer && - dynamic_cast(currentLayer)); - + (haveCurrentLayer && + currentLayer->isLayerEditable()); + bool haveCurrentTimeInstantsLayer = + (haveCurrentLayer && + dynamic_cast(currentLayer)); + bool haveCurrentTimeValueLayer = + (haveCurrentLayer && + dynamic_cast(currentLayer)); + bool alignMode = m_viewManager && m_viewManager->getAlignMode(); emit canChangeSolo(havePlayTarget && !alignMode); emit canAlign(havePlayTarget && m_document && m_document->canAlign()); @@ -2190,7 +2217,7 @@ emit canSpeedUpPlayback(v < m_playSpeed->maximum()); emit canSlowDownPlayback(v > m_playSpeed->minimum()); - if (m_viewManager && + if (m_viewManager && (m_viewManager->getToolMode() == ViewManager::MeasureMode)) { emit canDeleteSelection(haveCurrentLayer); m_deleteSelectedAction->setText(tr("&Delete Current Measurement")); @@ -2225,8 +2252,8 @@ MainWindow::updateDescriptionLabel() { if (!getMainModel()) { - m_descriptionLabel->setText(tr("No audio file loaded.")); - return; + m_descriptionLabel->setText(tr("No audio file loaded.")); + return; } QString description; @@ -2236,15 +2263,15 @@ if (m_playSource) tsr = m_playSource->getTargetSampleRate(); if (ssr != tsr) { - description = tr("%1Hz (resampling to %2Hz)").arg(ssr).arg(tsr); + description = tr("%1Hz (resampling to %2Hz)").arg(ssr).arg(tsr); } else { - description = QString("%1Hz").arg(ssr); + description = QString("%1Hz").arg(ssr); } description = QString("%1 - %2") - .arg(RealTime::frame2RealTime(getMainModel()->getEndFrame(), ssr) - .toText(false).c_str()) - .arg(description); + .arg(RealTime::frame2RealTime(getMainModel()->getEndFrame(), ssr) + .toText(false).c_str()) + .arg(description); m_descriptionLabel->setText(description); } @@ -2305,11 +2332,11 @@ QString path = getOpenFileName(FileFinder::AudioFile); if (path != "") { - if (openAudio(path, ReplaceSession) == FileOpenFailed) { + if (openAudio(path, ReplaceSession) == FileOpenFailed) { emit hideSplash(); - QMessageBox::critical(this, tr("Failed to open file"), - tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); - } + QMessageBox::critical(this, tr("Failed to open file"), + tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); + } } } @@ -2319,12 +2346,14 @@ QString path = getOpenFileName(FileFinder::AudioFile); if (path != "") { - if (openAudio(path, CreateAdditionalModel) == FileOpenFailed) { + if (openAudio(path, CreateAdditionalModel) == FileOpenFailed) { emit hideSplash(); - QMessageBox::critical(this, tr("Failed to open file"), - tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); - } + QMessageBox::critical(this, tr("Failed to open file"), + tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); + } } + + files_paths[int(m_paneStack->getPaneCount())-1] = path; } void @@ -2333,11 +2362,11 @@ QString path = getOpenFileName(FileFinder::AudioFile); if (path != "") { - if (openAudio(path, ReplaceMainModel) == FileOpenFailed) { + if (openAudio(path, ReplaceMainModel) == FileOpenFailed) { emit hideSplash(); - QMessageBox::critical(this, tr("Failed to open file"), - tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); - } + QMessageBox::critical(this, tr("Failed to open file"), + tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); + } } } @@ -2370,7 +2399,7 @@ if (!layer) continue; cerr << "layer = " << layer->objectName() << endl; Model *m = layer->getModel(); - RangeSummarisableTimeValueModel *wm = + RangeSummarisableTimeValueModel *wm = dynamic_cast(m); if (wm) { cerr << "found: " << wm->objectName() << endl; @@ -2437,19 +2466,19 @@ if (selections.size() == 1) { - QStringList items; - items << tr("Export the selected region only") - << tr("Export the whole audio file"); - - bool ok = false; - QString item = ListInputDialog::getItem - (this, tr("Select region to export"), - tr("Which region from the original audio file do you want to export?"), - items, 0, &ok); - - if (!ok || item.isEmpty()) return; - - if (item == items[0]) selectionToWrite = &ms; + QStringList items; + items << tr("Export the selected region only") + << tr("Export the whole audio file"); + + bool ok = false; + QString item = ListInputDialog::getItem + (this, tr("Select region to export"), + tr("Which region from the original audio file do you want to export?"), + items, 0, &ok); + + if (!ok || item.isEmpty()) return; + + if (item == items[0]) selectionToWrite = &ms; } else if (selections.size() > 1) { @@ -2474,44 +2503,43 @@ } else if (item == items[1]) { multiple = true; } - } else { // asData selectionToWrite = &ms; } if (multiple) { // Can only happen when asData false - int n = 1; - QString base = path; - base.replace(".wav", ""); - - for (MultiSelection::SelectionList::iterator i = selections.begin(); - i != selections.end(); ++i) { - - MultiSelection subms; - subms.setSelection(*i); - - QString subpath = QString("%1.%2.wav").arg(base).arg(n); - ++n; - - if (QFileInfo(subpath).exists()) { - error = tr("Fragment file %1 already exists, aborting").arg(subpath); - break; - } - - WavFileWriter subwriter(subpath, + int n = 1; + QString base = path; + base.replace(".wav", ""); + + for (MultiSelection::SelectionList::iterator i = selections.begin(); + i != selections.end(); ++i) { + + MultiSelection subms; + subms.setSelection(*i); + + QString subpath = QString("%1.%2.wav").arg(base).arg(n); + ++n; + + if (QFileInfo(subpath).exists()) { + error = tr("Fragment file %1 already exists, aborting").arg(subpath); + break; + } + + WavFileWriter subwriter(subpath, model->getSampleRate(), model->getChannelCount(), WavFileWriter::WriteToTemporary); subwriter.writeModel(model, &subms); - ok = subwriter.isOK(); - - if (!ok) { - error = subwriter.getError(); - break; - } - } - } + ok = subwriter.isOK(); + + if (!ok) { + error = subwriter.getError(); + break; + } + } + } } if (!multiple) { @@ -2545,25 +2573,28 @@ m_recentFiles.addFile(path); } } else { - QMessageBox::critical(this, tr("Failed to write file"), error); + QMessageBox::critical(this, tr("Failed to write file"), error); } } + + + void MainWindow::importLayer() { Pane *pane = m_paneStack->getCurrentPane(); - + if (!pane) { - // shouldn't happen, as the menu action should have been disabled - std::cerr << "WARNING: MainWindow::importLayer: no current pane" << std::endl; - return; + // shouldn't happen, as the menu action should have been disabled + std::cerr << "WARNING: MainWindow::importLayer: no current pane" << std::endl; + return; } if (!getMainModel()) { - // shouldn't happen, as the menu action should have been disabled - std::cerr << "WARNING: MainWindow::importLayer: No main model -- hence no default sample rate available" << std::endl; - return; + // shouldn't happen, as the menu action should have been disabled + std::cerr << "WARNING: MainWindow::importLayer: No main model -- hence no default sample rate available" << std::endl; + return; } QString path = getOpenFileName(FileFinder::LayerFile); @@ -2571,7 +2602,7 @@ if (path != "") { FileOpenStatus status = openLayer(path); - + if (status == FileOpenFailed) { emit hideSplash(); QMessageBox::critical(this, tr("Failed to open file"), @@ -2684,7 +2715,7 @@ { Pane *pane = m_paneStack->getCurrentPane(); if (!pane) return; - + QString path = getSaveFileName(FileFinder::ImageFile); if (path == "") return; @@ -2699,7 +2730,7 @@ pane->getLastVisibleFrame()); size_t sf0 = 0, sf1 = 0; - + if (haveSelection) { MultiSelection::SelectionList selections = m_viewManager->getSelections(); sf0 = selections.begin()->getStartFrame(); @@ -2743,7 +2774,7 @@ bool ok = lid->exec(); QString item = lid->getCurrentString(); delete lid; - + if (!ok || item.isEmpty()) return; settings.setValue("lastimageexportregion", deflt); @@ -2765,7 +2796,7 @@ QMessageBox::critical(this, tr("Failed to save image file"), tr("Failed to save image file %1").arg(path)); } - + delete image; } @@ -2783,8 +2814,8 @@ this, SLOT(contextHelpChanged(const QString &))); if (!m_timeRulerLayer) { - m_timeRulerLayer = m_document->createMainModelLayer - (LayerFactory::TimeRuler); + m_timeRulerLayer = m_document->createMainModelLayer + (LayerFactory::TimeRuler); } m_document->addLayerToView(pane, m_timeRulerLayer); @@ -2816,29 +2847,29 @@ while (m_paneStack->getPaneCount() > 0) { - Pane *pane = m_paneStack->getPane(m_paneStack->getPaneCount() - 1); - - while (pane->getLayerCount() > 0) { - m_document->removeLayerFromView - (pane, pane->getLayer(pane->getLayerCount() - 1)); - } - - m_overview->unregisterView(pane); - m_paneStack->deletePane(pane); + Pane *pane = m_paneStack->getPane(m_paneStack->getPaneCount() - 1); + + while (pane->getLayerCount() > 0) { + m_document->removeLayerFromView + (pane, pane->getLayer(pane->getLayerCount() - 1)); } + m_overview->unregisterView(pane); + m_paneStack->deletePane(pane); + } + while (m_paneStack->getHiddenPaneCount() > 0) { - Pane *pane = m_paneStack->getHiddenPane - (m_paneStack->getHiddenPaneCount() - 1); - - while (pane->getLayerCount() > 0) { - m_document->removeLayerFromView - (pane, pane->getLayer(pane->getLayerCount() - 1)); - } - - m_overview->unregisterView(pane); - m_paneStack->deletePane(pane); + Pane *pane = m_paneStack->getHiddenPane + (m_paneStack->getHiddenPaneCount() - 1); + + while (pane->getLayerCount() > 0) { + m_document->removeLayerFromView + (pane, pane->getLayer(pane->getLayerCount() - 1)); + } + + m_overview->unregisterView(pane); + m_paneStack->deletePane(pane); } delete m_layerTreeDialog.data(); @@ -2875,8 +2906,8 @@ if (openSessionFile(path) == FileOpenFailed) { emit hideSplash(); - QMessageBox::critical(this, tr("Failed to open file"), - tr("File open failed

Session file \"%1\" could not be opened").arg(path)); + QMessageBox::critical(this, tr("Failed to open file"), + tr("File open failed

Session file \"%1\" could not be opened").arg(path)); } } @@ -2902,6 +2933,11 @@ QMessageBox::critical(this, tr("Failed to open file"), tr("Audio required

Unable to load layer data from \"%1\" without an audio file.
Please load at least one audio file before importing annotations.").arg(path)); } + + files_paths[0] = path; + QTextStream out(stdout); + out << path; + } void @@ -2941,11 +2977,11 @@ { QObject *obj = sender(); QAction *action = dynamic_cast(obj); - + if (!action) { - std::cerr << "WARNING: MainWindow::openRecentFile: sender is not an action" - << std::endl; - return; + std::cerr << "WARNING: MainWindow::openRecentFile: sender is not an action" + << std::endl; + return; } QString path = action->text(); @@ -2971,9 +3007,9 @@ QAction *action = qobject_cast(s); if (!action) { - std::cerr << "WARNING: MainWindow::applyTemplate: sender is not an action" - << std::endl; - return; + std::cerr << "WARNING: MainWindow::applyTemplate: sender is not an action" + << std::endl; + return; } QString n = action->objectName(); @@ -3010,14 +3046,14 @@ layout->addWidget(lineEdit, 1, 0); QCheckBox *makeDefault = new QCheckBox(tr("Set as default template for future audio files")); layout->addWidget(makeDefault, 2, 0); - + QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); layout->addWidget(bb, 3, 0); connect(bb, SIGNAL(accepted()), d, SLOT(accept())); connect(bb, SIGNAL(accepted()), d, SLOT(accept())); connect(bb, SIGNAL(rejected()), d, SLOT(reject())); - + if (d->exec() == QDialog::Accepted) { QString name = lineEdit->text(); @@ -3055,19 +3091,19 @@ MainWindow::paneAdded(Pane *pane) { if (m_overview) m_overview->registerView(pane); -} +} void MainWindow::paneHidden(Pane *pane) { - if (m_overview) m_overview->unregisterView(pane); -} + if (m_overview) m_overview->unregisterView(pane); +} void MainWindow::paneAboutToBeDeleted(Pane *pane) { - if (m_overview) m_overview->unregisterView(pane); -} + if (m_overview) m_overview->unregisterView(pane); +} void MainWindow::paneDropAccepted(Pane *pane, QStringList uriList) @@ -3106,8 +3142,8 @@ if (pane) m_paneStack->setCurrentPane(pane); QUrl testUrl(text); - if (testUrl.scheme() == "file" || - testUrl.scheme() == "http" || + if (testUrl.scheme() == "file" || + testUrl.scheme() == "http" || testUrl.scheme() == "ftp") { QStringList list; list.push_back(text); @@ -3126,14 +3162,14 @@ if (m_openingAudioFile) { // std::cerr << "Busy - ignoring close event" << std::endl; - e->ignore(); - return; + e->ignore(); + return; } if (!m_abandoning && !checkSaveModified()) { // std::cerr << "Close refused by user - ignoring close event" << endl; - e->ignore(); - return; + e->ignore(); + return; } QSettings settings; @@ -3189,7 +3225,7 @@ } else { if (!QFileInfo(svDir).isDir()) return false; } - + // This name doesn't have to be unguessable #ifndef _WIN32 QString fname = QString("tmp-%1-%2.sv") @@ -3221,23 +3257,23 @@ emit hideSplash(); - int button = - QMessageBox::warning(this, - tr("Session modified"), - tr("Session modified

The current session has been modified.
Do you want to save it?"), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + int button = + QMessageBox::warning(this, + tr("Session modified"), + tr("Session modified

The current session has been modified.
Do you want to save it?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes); if (button == QMessageBox::Yes) { - saveSession(); - if (m_documentModified) { // save failed -- don't proceed! - return false; - } else { + saveSession(); + if (m_documentModified) { // save failed -- don't proceed! + return false; + } else { return true; // saved, so it's safe to continue now } } else if (button == QMessageBox::No) { - m_documentModified = false; // so we know to abandon it - return true; + m_documentModified = false; // so we know to abandon it + return true; } // else cancel @@ -3255,7 +3291,7 @@ bool prevNewSession = settings.value("newsessionforrdfaudio", true).toBool(); settings.endGroup(); bool newSession = true; - + QStringList items; items << tr("Close the current session and create a new one") << tr("Add this data to the current session"); @@ -3265,12 +3301,12 @@ (this, tr("Select target for import"), tr("Select a target for import

This RDF document refers to one or more audio files.
You already have an audio waveform loaded.
What would you like to do with the new data?"), items, prevNewSession ? 0 : 1, &ok); - + if (!ok || item.isEmpty()) { *cancel = true; return false; } - + newSession = (item == items[0]); settings.beginGroup("MainWindow"); settings.setValue("newsessionforrdfaudio", newSession); @@ -3284,15 +3320,15 @@ MainWindow::saveSession() { if (m_sessionFile != "") { - if (!saveSessionFile(m_sessionFile)) { - QMessageBox::critical(this, tr("Failed to save file"), - tr("Save failed

Session file \"%1\" could not be saved.").arg(m_sessionFile)); - } else { - CommandHistory::getInstance()->documentSaved(); - documentRestored(); - } + if (!saveSessionFile(m_sessionFile)) { + QMessageBox::critical(this, tr("Failed to save file"), + tr("Save failed

Session file \"%1\" could not be saved.").arg(m_sessionFile)); } else { - saveSessionAs(); + CommandHistory::getInstance()->documentSaved(); + documentRestored(); + } + } else { + saveSessionAs(); } } @@ -3308,15 +3344,15 @@ if (path == "") return; if (!saveSessionFile(path)) { - QMessageBox::critical(this, tr("Failed to save file"), - tr("Save failed

Session file \"%1\" could not be saved.").arg(path)); + QMessageBox::critical(this, tr("Failed to save file"), + tr("Save failed

Session file \"%1\" could not be saved.").arg(path)); } else { - setWindowTitle(tr("%1: %1") + setWindowTitle(tr("%1: %1") .arg(QApplication::applicationName()) - .arg(QFileInfo(path).fileName())); - m_sessionFile = path; - CommandHistory::getInstance()->documentSaved(); - documentRestored(); + .arg(QFileInfo(path).fileName())); + m_sessionFile = path; + CommandHistory::getInstance()->documentSaved(); + documentRestored(); m_recentFiles.addFile(path); emit activity(tr("Save session as \"%1\"").arg(path)); } @@ -3334,8 +3370,8 @@ } else { m_panLayer->setBaseColour (ColourDatabase::getInstance()->getColourIndex(tr("Green"))); - } - } + } + } } void @@ -3346,7 +3382,7 @@ if (!m_playControlsSpacer) return; int spacerWidth = width - m_playControlsWidth - 4; - + // SVDEBUG << "resizing spacer from " << m_playControlsSpacer->width() << " to " << spacerWidth << endl; m_playControlsSpacer->setFixedSize(QSize(spacerWidth, 2)); @@ -3357,19 +3393,19 @@ { QObject *s = sender(); QAction *action = dynamic_cast(s); - + if (!action) { - std::cerr << "WARNING: MainWindow::addPane: sender is not an action" - << std::endl; - return; + std::cerr << "WARNING: MainWindow::addPane: sender is not an action" + << std::endl; + return; } PaneActionMap::iterator i = m_paneActions.find(action); if (i == m_paneActions.end()) { - std::cerr << "WARNING: MainWindow::addPane: unknown action " - << action->objectName() << std::endl; - return; + std::cerr << "WARNING: MainWindow::addPane: unknown action " + << action->objectName() << std::endl; + return; } addPane(i->second, action->text()); @@ -3394,15 +3430,15 @@ if (configuration.layer != LayerFactory::TimeRuler && configuration.layer != LayerFactory::Spectrum) { - if (!m_timeRulerLayer) { + if (!m_timeRulerLayer) { // std::cerr << "no time ruler layer, creating one" << std::endl; - m_timeRulerLayer = m_document->createMainModelLayer - (LayerFactory::TimeRuler); - } + m_timeRulerLayer = m_document->createMainModelLayer + (LayerFactory::TimeRuler); + } // SVDEBUG << "adding time ruler layer " << m_timeRulerLayer << endl; - m_document->addLayerToView(pane, m_timeRulerLayer); + m_document->addLayerToView(pane, m_timeRulerLayer); } Layer *newLayer = m_document->createLayer(configuration.layer); @@ -3454,27 +3490,27 @@ { QObject *s = sender(); QAction *action = dynamic_cast(s); - + if (!action) { - std::cerr << "WARNING: MainWindow::addLayer: sender is not an action" - << std::endl; - return; + std::cerr << "WARNING: MainWindow::addLayer: sender is not an action" + << std::endl; + return; } Pane *pane = m_paneStack->getCurrentPane(); - + if (!pane) { - std::cerr << "WARNING: MainWindow::addLayer: no current pane" << std::endl; - return; + std::cerr << "WARNING: MainWindow::addLayer: no current pane" << std::endl; + return; } ExistingLayerActionMap::iterator ei = m_existingLayerActions.find(action); if (ei != m_existingLayerActions.end()) { - Layer *newLayer = ei->second; - m_document->addLayerToView(pane, newLayer); - m_paneStack->setCurrentLayer(pane, newLayer); - return; + Layer *newLayer = ei->second; + m_document->addLayerToView(pane, newLayer); + m_paneStack->setCurrentLayer(pane, newLayer); + return; } ei = m_sliceActions.find(action); @@ -3491,39 +3527,40 @@ dest, SLOT(sliceableModelReplaced(const Model *, const Model *))); connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)), dest, SLOT(modelAboutToBeDeleted(Model *))); + } - m_document->addLayerToView(pane, newLayer); - m_paneStack->setCurrentLayer(pane, newLayer); - return; + m_document->addLayerToView(pane, newLayer); + m_paneStack->setCurrentLayer(pane, newLayer); + return; } TransformActionMap::iterator i = m_transformActions.find(action); if (i == m_transformActions.end()) { - LayerActionMap::iterator i = m_layerActions.find(action); - - if (i == m_layerActions.end()) { - std::cerr << "WARNING: MainWindow::addLayer: unknown action " - << action->objectName() << std::endl; - return; - } - - LayerFactory::LayerType type = i->second.layer; - - LayerFactory::LayerTypeSet emptyTypes = - LayerFactory::getInstance()->getValidEmptyLayerTypes(); - - Layer *newLayer = 0; - - if (emptyTypes.find(type) != emptyTypes.end()) { - - newLayer = m_document->createEmptyLayer(type); + LayerActionMap::iterator i = m_layerActions.find(action); + + if (i == m_layerActions.end()) { + std::cerr << "WARNING: MainWindow::addLayer: unknown action " + << action->objectName() << std::endl; + return; + } + + LayerFactory::LayerType type = i->second.layer; + + LayerFactory::LayerTypeSet emptyTypes = + LayerFactory::getInstance()->getValidEmptyLayerTypes(); + + Layer *newLayer = 0; + + if (emptyTypes.find(type) != emptyTypes.end()) { + + newLayer = m_document->createEmptyLayer(type); if (newLayer) { m_toolActions[ViewManager::DrawMode]->trigger(); } - } else { + } else { Model *model = i->second.sourceModel; @@ -3568,7 +3605,7 @@ m_paneStack->setCurrentLayer(pane, newLayer); } - return; + return; } //!!! want to do something like this, but it's not supported in @@ -3577,11 +3614,11 @@ int channel = -1; // pick up the default channel from any existing layers on the same pane for (int j = 0; j < pane->getLayerCount(); ++j) { - int c = LayerFactory::getInstance()->getChannel(pane->getLayer(j)); - if (c != -1) { - channel = c; - break; - } + int c = LayerFactory::getInstance()->getChannel(pane->getLayer(j)); + if (c != -1) { + channel = c; + break; + } } */ @@ -3595,12 +3632,12 @@ } void -MainWindow::addLayer(QString transformId) +MainWindow:: addLayer(QString transformId) { Pane *pane = m_paneStack->getCurrentPane(); if (!pane) { - std::cerr << "WARNING: MainWindow::addLayer: no current pane" << std::endl; - return; + std::cerr << "WARNING: MainWindow::addLayer: no current pane" << std::endl; + return; } Transform transform = TransformFactory::getInstance()-> @@ -3626,7 +3663,7 @@ } if (defaultInputModel) break; } - + size_t startFrame = 0, duration = 0; size_t endFrame = 0; m_viewManager->getSelection().getExtents(startFrame, endFrame); @@ -3666,18 +3703,18 @@ { Pane *pane = m_paneStack->getCurrentPane(); if (pane) { - Layer *layer = pane->getSelectedLayer(); - if (layer) { - bool ok = false; - QString newName = QInputDialog::getText - (this, tr("Rename Layer"), - tr("New name for this layer:"), - QLineEdit::Normal, layer->objectName(), &ok); - if (ok) { - layer->setPresentationName(newName); - setupExistingLayersMenus(); - } - } + Layer *layer = pane->getSelectedLayer(); + if (layer) { + bool ok = false; + QString newName = QInputDialog::getText + (this, tr("Rename Layer"), + tr("New name for this layer:"), + QLineEdit::Normal, layer->objectName(), &ok); + if (ok) { + layer->setPresentationName(newName); + setupExistingLayersMenus(); + } + } } } @@ -3691,7 +3728,7 @@ } TransformId transform = finder->getTransform(); delete finder; - + if (getMainModel() != 0 && m_paneStack->getCurrentPane() != 0) { addLayer(transform); } @@ -3708,13 +3745,13 @@ MainWindow::alignToggled() { QAction *action = dynamic_cast(sender()); - + if (!m_viewManager) return; if (action) { - m_viewManager->setAlignMode(action->isChecked()); + m_viewManager->setAlignMode(action->isChecked()); } else { - m_viewManager->setAlignMode(!m_viewManager->getAlignMode()); + m_viewManager->setAlignMode(!m_viewManager->getAlignMode()); } if (m_viewManager->getAlignMode()) { @@ -3740,8 +3777,8 @@ for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { - Pane *pane = m_paneStack->getPane(i); - if (!pane) continue; + Pane *pane = m_paneStack->getPane(i); + if (!pane) continue; pane->update(); } @@ -3809,7 +3846,7 @@ Layer *layer = pane->getLayer(i); if (LayerFactory::getInstance()->getLayerType(layer) == LayerFactory::Waveform) { - RangeSummarisableTimeValueModel *tvm = + RangeSummarisableTimeValueModel *tvm = dynamic_cast(layer->getModel()); if (tvm) { m_panLayer->setModel(tvm); @@ -3914,7 +3951,7 @@ (this, tr("Sample rate mismatch"), tr("Wrong sample rate

The sample rate of this audio file (%1 Hz) does not match\nthe current playback rate (%2 Hz).

The file will play at the wrong speed and pitch.

Change the Resample mismatching files on import option under File -> Preferences if you want to alter this behaviour.") .arg(requested).arg(actual)); - } + } updateDescriptionLabel(); } @@ -4014,7 +4051,7 @@ if (!noteOn) continue; insertInstantAt(ev.getTime()); } -} +} void MainWindow::playStatusChanged(bool playing) @@ -4075,7 +4112,7 @@ if (!a) return; int type = m_numberingActions[a]; - + if (m_labeller) m_labeller->setType(Labeller::ValueType(type)); QSettings settings; @@ -4089,12 +4126,12 @@ { QAction *a = dynamic_cast(sender()); if (!a) return; - + int cycle = a->text().toInt(); if (cycle == 0) return; if (m_labeller) m_labeller->setCounterCycleSize(cycle); - + QSettings settings; settings.beginGroup("MainWindow"); settings.setValue("labellercycle", cycle); @@ -4411,7 +4448,7 @@ aboutText.replace(tr("With "), tr("Using ")); #endif - aboutText += + aboutText += "

Sonic Visualiser Copyright © 2005–2013 Chris Cannam and " "Queen Mary, University of London.

" "

This program is free software; you can redistribute it and/or " @@ -4419,7 +4456,7 @@ "published by the Free Software Foundation; either version 2 of the " "License, or (at your option) any later version.
See the file " "COPYING included with this distribution for more information.

"; - + QMessageBox::about(this, tr("About Sonic Visualiser"), aboutText); } @@ -4445,3 +4482,768 @@ } + +CheckBox::CheckBox(QWidget *parent) + : QWidget(parent) +{ +// SELECTION RULES + QGroupBox *selrule_box = new QGroupBox(QString::fromUtf8("SELECTION RULES"),this); + selrule_box->setFont(QFont("Times", 9, QFont::Bold)); + selrule_box->move(5,5); + selrule_box->resize(235,130); + QButtonGroup *selrule_group = new QButtonGroup(this); + selrule_group->setObjectName("Selection Rule"); + + QRadioButton *minmax_rule = new QRadioButton(QString::fromUtf8("Min/Max Rule"),this); + minmax_rule->move(20,25); + minmax_rule->setObjectName("0"); + QRadioButton *exclusion_rule = new QRadioButton(QString::fromUtf8("Exclusion Rule"),this); + exclusion_rule->move(20,45); + exclusion_rule->setObjectName("1"); + QRadioButton *notmute_rule = new QRadioButton(QString::fromUtf8("Not Mute Rule"),this); + notmute_rule->move(130,25); + notmute_rule->setObjectName("2"); + QRadioButton *implication_rule = new QRadioButton(QString::fromUtf8("Implication Rule"),this); + implication_rule->move(130,45); + implication_rule->setObjectName("3"); + + selrule_group->addButton(minmax_rule); + selrule_group->addButton(exclusion_rule); + selrule_group->addButton(notmute_rule); + selrule_group->addButton(implication_rule); + + QSpinBox *sel_par1 = new QSpinBox(this); + sel_par1->setEnabled(true); + sel_par1->setGeometry(QRect(20, 75, 40, 20)); + sel_par1->setMinimum(1); + sel_par1->setMaximum(numtracks); + selrule_par1 = sel_par1->value(); + + sel_rule1 = new QLabel(this); + sel_rule1->setText("Parameter 1"); + sel_rule1->setGeometry(70, 75, 100, 20); + + QSpinBox *sel_par2 = new QSpinBox(this); + sel_par2->setEnabled(true); + sel_par2->setGeometry(QRect(20, 100, 40, 20)); + sel_par2->setMinimum(1); + sel_par2->setMaximum(numtracks); + selrule_par2 = sel_par2->value(); + + sel_rule2 = new QLabel(this); + sel_rule2->setText("Parameter 2"); + sel_rule2->setGeometry(70, 100, 100, 20); + + connect(selrule_group, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(set_selruleType(QAbstractButton*))); + connect(sel_par1, SIGNAL(valueChanged(int)), this, SLOT(set_selrulePAR1(int))); + connect(sel_par2, SIGNAL(valueChanged(int)), this, SLOT(set_selrulePAR2(int))); + +// MIXING RULES (yet to implement) + QGroupBox *mixrule_box = new QGroupBox(QString::fromUtf8("MIXING RULES"),this); + mixrule_box->setFont(QFont("Times", 9, QFont::Bold)); + mixrule_box->move(255,5); + mixrule_box->resize(330,130); + QButtonGroup *mixrule_group = new QButtonGroup(this); + mixrule_group->setObjectName("Mixing Rule"); + + QRadioButton *equivalence_rule = new QRadioButton(QString::fromUtf8("Equivalence Rule"),this); + equivalence_rule->move(270,25); + equivalence_rule->setObjectName("0"); + QRadioButton *upper_rule = new QRadioButton(QString::fromUtf8("Upper Rule"),this); + upper_rule->move(270,45); + upper_rule->setObjectName("1"); + QRadioButton *lower_rule = new QRadioButton(QString::fromUtf8("Lower Rule"),this); + lower_rule->move(380,25); + lower_rule->setObjectName("2"); + QRadioButton *limit_rule = new QRadioButton(QString::fromUtf8("Limit Rule"),this); + limit_rule->move(380,45); + limit_rule->setObjectName("3"); + + mixrule_group->addButton(equivalence_rule); + mixrule_group->addButton(upper_rule); + mixrule_group->addButton(lower_rule); + mixrule_group->addButton(limit_rule); + + QSpinBox *mix_par1 = new QSpinBox(this); + mix_par1->setEnabled(true); + mix_par1->setGeometry(QRect(270, 75, 40, 20)); + mix_par1->setMinimum(1); + mix_par1->setMaximum(numtracks); + mixrule_par1 = mix_par1->value(); + + mix_rule1 = new QLabel(this); + mix_rule1->setText("Parameter 1"); + mix_rule1->setGeometry(320, 75, 100, 20); + + QSpinBox *mix_par2 = new QSpinBox(this); + mix_par2->setEnabled(true); + mix_par2->setGeometry(QRect(270, 100, 40, 20)); + mix_par2->setMinimum(1); + mix_par2->setMaximum(numtracks); + mixrule_par2 = mix_par2->value(); + + mix_rule2 = new QLabel(this); + mix_rule2->setText("Parameter 2"); + mix_rule2->setGeometry(320, 100, 100, 20); + + QSpinBox *mix_par3 = new QSpinBox(this); + mix_par3->setEnabled(true); + mix_par3->setGeometry(QRect(410, 75, 40, 20)); + mix_par3->setMinimum(0); + mix_par3->setMaximum(100); + mixrule_par3 = mix_par3->value(); + + mix_rule3 = new QLabel(this); + mix_rule3->setText("Parameter 3"); + mix_rule3->setGeometry(460, 75, 100, 20); + + QSpinBox *mix_par4 = new QSpinBox(this); + mix_par4->setEnabled(true); + mix_par4->setGeometry(QRect(410, 100, 40, 20)); + mix_par4->setMinimum(0); + mix_par4->setMaximum(100); + mixrule_par4 = mix_par4->value(); + + mix_rule4 = new QLabel(this); + mix_rule4->setText("Parameter 4"); + mix_rule4->setGeometry(460, 100, 100, 20); + + connect(mixrule_group, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(set_mixruleType(QAbstractButton*))); + connect(mix_par1, SIGNAL(valueChanged(int)), this, SLOT(set_mixrulePAR1(int))); + connect(mix_par2, SIGNAL(valueChanged(int)), this, SLOT(set_mixrulePAR2(int))); + connect(mix_par3, SIGNAL(valueChanged(int)), this, SLOT(set_mixrulePAR3(int))); + connect(mix_par4, SIGNAL(valueChanged(int)), this, SLOT(set_mixrulePAR4(int))); +// connect(equivalence_rule, SIGNAL(toggled(bool)), mix_rule1, SLOT() + +// GROUPS + QGroupBox *group_box = new QGroupBox(QString::fromUtf8("GROUPS"),this); + group_box->setFont(QFont("Times", 9, QFont::Bold)); + group_box->move(5,150); + group_box->resize(580,100); + + group_label = new QLabel(this); + group_label->setText("Select tracks for the group:"); + group_label->setGeometry(20, 165, 200, 20); + + QButtonGroup *group_cb = new QButtonGroup(this); + group_cb->setObjectName("Group"); + + for (int i=1; i<=numtracks; i++) { + QCheckBox *track_cb = new QCheckBox(QString::number(i), this); + track_cb->setGeometry(80*i,185,95,30); + track_cb->setObjectName(QString::number(i)); + group_cb->setExclusive(false); + group_cb->addButton(track_cb); + } + + QSpinBox *group_vol = new QSpinBox(this); + group_vol->setEnabled(true); + group_vol->setGeometry(QRect(280, 220, 40, 20)); + group_vol->setMinimum(0); + group_vol->setMaximum(100); + group_vol->setValue(100); + group_volume = group_vol->value(); + + grp_vol = new QLabel(this); + grp_vol->setText("Group Volume"); + grp_vol->setGeometry(330, 220, 100, 20); + + group_name_line = new QLineEdit(this); + group_name_line->setGeometry(25,220,150,20); + group_name_line->setText("Insert a name"); + group_name_line->setMaxLength(20); + + grp_name = new QLabel(this); + grp_name->setText("Group Name"); + grp_name->setGeometry(180,220,100,20); + + connect(group_cb, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(set_TrackInGroup(QAbstractButton*))); + connect(group_name_line, SIGNAL(textChanged(QString)), this, SLOT(set_GroupName(QString))); + connect(group_vol, SIGNAL(valueChanged(int)), this, SLOT(set_GroupVolume(int))); + +// PRESETS + QGroupBox *preset_box = new QGroupBox(QString::fromUtf8("PRESETS"),this); + preset_box->setFont(QFont("Times", 9, QFont::Bold)); + preset_box->move(5,270); + preset_box->resize(580,90); + + QButtonGroup *preset_group = new QButtonGroup(this); + preset_group->setObjectName("Presets"); + + QRadioButton *static_preset = new QRadioButton(QString::fromUtf8("Static Volume"),this); + static_preset->move(20,290); + static_preset->setObjectName("0"); + + QRadioButton *dynamic_preset = new QRadioButton(QString::fromUtf8("Dynamic Volume"),this); + dynamic_preset->move(150,290); + dynamic_preset->setObjectName("4"); + + preset_group->addButton(static_preset); + preset_group->addButton(dynamic_preset); + + QButtonGroup *fade_group = new QButtonGroup(this); + fade_group->setObjectName("Fade IN/OUT"); + + QRadioButton *fade_in = new QRadioButton(QString::fromUtf8("Fade IN"),this); + fade_in->move(170,310); + fade_in->setObjectName("1"); + fade_in->setDisabled(true); + + QRadioButton *fade_out = new QRadioButton(QString::fromUtf8("Fade OUT"),this); + fade_out->move(170,330); + fade_out->setObjectName("0"); + fade_out->setDisabled(true); + + fade_group->addButton(fade_in); + fade_group->addButton(fade_out); + + connect(preset_group, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(set_presetType(QAbstractButton*))); + connect(dynamic_preset, SIGNAL(toggled(bool)), fade_in, SLOT(setEnabled(bool))); + connect(dynamic_preset, SIGNAL(toggled(bool)), fade_out, SLOT(setEnabled(bool))); + connect(fade_group, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(set_fade(QAbstractButton*))); + + +// IMAGE AND LYRICS + QCheckBox *text_cb = new QCheckBox("Include lyrics", this); + text_cb->setGeometry(20, 380, 95, 30); + QCheckBox *jpeg_cb = new QCheckBox("Include picture", this); + jpeg_cb->setGeometry(20, 430, 95, 30); + + line->setGeometry(120, 380, 320, 30); + line2->setGeometry(120, 430, 320, 30); + + QPushButton *create = new QPushButton("Export", this); + create->setGeometry(20, 500, 95, 30); + + QPushButton *TextFilePath = new QPushButton("Select text file", this); + TextFilePath->setGeometry(460, 380, 95, 30); + TextFilePath->setDisabled(true); + + QPushButton *JpegFilePath = new QPushButton("Select JPEG file", this); + JpegFilePath->setGeometry(460, 430, 95, 30); + JpegFilePath->setDisabled(true); + + // Enable/disable push buttons + connect(text_cb, SIGNAL(toggled(bool)), TextFilePath, SLOT(setEnabled(bool))); + connect(jpeg_cb, SIGNAL(toggled(bool)), JpegFilePath, SLOT(setEnabled(bool))); + // Check the inclusion of image and text + connect(text_cb, SIGNAL(stateChanged(int)), this, SLOT(insertLyrics(int))); // yet to implement + connect(jpeg_cb, SIGNAL(stateChanged(int)), this, SLOT(insertImage(int))); + // Set image and text paths + connect(TextFilePath, SIGNAL(clicked()), this , SLOT(defineImafTextFile())); + connect(JpegFilePath, SIGNAL(clicked()), this , SLOT(defineImafImageFile())); + // Create the file + connect(create, SIGNAL(clicked()), this , SLOT(saveImafFile())); + connect(create, SIGNAL(clicked()), this, SLOT(close())); +} + +void CheckBox::insertImage(int state) +{ + if (state) { + has_image = true; + } else{ + has_image = false; + } +} + +void CheckBox::insertLyrics(int state) +{ + if (state) { + has_lyrics = true; + } else{ + has_lyrics = false; + } +} + +void CheckBox::saveImafFile() +{ + ImafFileName = QFileDialog::getSaveFileName(this, tr("Save IMAF"), "/", tr("IMAF (*.ima)")); + + group_descr = "Thisgroup"; + + if( ImafFileName != "" ){ //if the user press cancel the function mainIMAFencoder won´t be called + mainIMAFencoder(numtracks, files_paths, ImafFileName, ImageFileName, TextFileName, + ImafVolumeValues, has_image, has_lyrics, selrule_type, selrule_par1, selrule_par2, + mixrule_type, mixrule_par1, mixrule_par2, mixrule_par3, mixrule_par4, + group_tracks, group_volume, group_name, group_descr, preset_type, fade_in); + } +} + +void CheckBox::defineImafImageFile() +{ + ImageFileName = QFileDialog::getOpenFileName(this, tr("Select JPEG"), "/", tr("JPEG (*.jpg)")); + line2->setText(ImageFileName); +} + +void CheckBox::defineImafTextFile() +{ + TextFileName = QFileDialog::getOpenFileName(this, tr("Select text file"), "/", tr("Text File (*.3gp)")); + line->setText(TextFileName); +} + +void +MainWindow::exportIMAF() +{ + numtracks = m_paneStack->getPaneCount(); + + for (int i = 0; i < numtracks; ++i) { + //ImafVolumeValues[i] = int(m_paneStack->getPane(i)->getLayer(0)->getPlayParameters()->getVolImaf())/2; + } + + CheckBox *imaf_window = new CheckBox(); + + imaf_window->resize(600,540); + imaf_window->move(100,100); + imaf_window->setWindowTitle("Export IMAF"); + imaf_window->show(); +} + + + +void MainWindow::insertLyrics(size_t frame, QString text){ + Pane *pane = m_paneStack->getCurrentPane(); + + + pane = m_paneStack->getCurrentPane(); + if (!pane) { + return; + } + + frame = pane->alignFromReference(frame); + + Layer *layer = dynamic_cast + (pane->getSelectedLayer()); + + if (!layer) { + for (int i = pane->getLayerCount(); i > 0; --i) { + layer = dynamic_cast(pane->getLayer(i - 1)); + if (layer) break; + } + + if (!layer) { + CommandHistory::getInstance()->startCompoundOperation + (tr("Add Point"), true); + layer = m_document->createEmptyLayer(LayerFactory::TimeInstants); + if (layer) { + m_document->addLayerToView(pane, layer); + m_paneStack->setCurrentLayer(pane, layer); + } + CommandHistory::getInstance()->endCompoundOperation(); + } + } + + if (layer) { + + Model *model = layer->getModel(); + SparseOneDimensionalModel *sodm = dynamic_cast + (model); + + if (sodm) { + SparseOneDimensionalModel::Point point(frame, ""); + + SparseOneDimensionalModel::Point prevPoint(0); + bool havePrevPoint = false; + + SparseOneDimensionalModel::EditCommand *command = + new SparseOneDimensionalModel::EditCommand(sodm, tr("Add Point")); + + if (m_labeller->requiresPrevPoint()) { + + SparseOneDimensionalModel::PointList prevPoints = + sodm->getPreviousPoints(frame); + + if (!prevPoints.empty()) { + prevPoint = *prevPoints.begin(); + havePrevPoint = true; + } + } + + if (m_labeller) { + + m_labeller->setSampleRate(sodm->getSampleRate()); + + if (m_labeller->actingOnPrevPoint()) { + command->deletePoint(prevPoint); + } + + m_labeller->label + (point, havePrevPoint ? &prevPoint : 0); + + if (m_labeller->actingOnPrevPoint()) { + command->addPoint(prevPoint); + } + } + point.label=text; + command->addPoint(point); + + command->setName(tr("Add Point at %1 s") + .arg(RealTime::frame2RealTime + (frame, + sodm->getSampleRate()) + .toText(false).c_str())); + + Command *c = command->finish(); + if (c) CommandHistory::getInstance()->addCommand(c, false); + } + } + +} + +void MainWindow::importIMAF() +{ + + QString filename; + int haslyrics; // if this variable != 2 -> there are lyrics + filename = QFileDialog::getOpenFileName(this, + tr("Import IMAF"), "/", tr("IMAF (*.ima)")); + + if (filename.isEmpty()) return; + isIMAF = true; + + haslyrics = mainIMAFdecoder(filename); + + openMP3IMAF(); + + if (haslyrics!=2){ + addPaneToStack();//it creates a new pane to show the lyrics + + Pane *pane = m_paneStack->getCurrentPane(); + LayerFactory::LayerType type ; //set the type of layer + type = LayerFactory::TimeInstants; + //create a new layer + Layer *newLayer = 0; + newLayer = m_document->createEmptyLayer(type); + m_toolActions[ViewManager::DrawMode]->trigger(); + m_document->addLayerToView(pane, newLayer); + + //create a new layer + Layer *newLayer1 = 0; + newLayer1 = m_document->createEmptyLayer(type); + m_toolActions[ViewManager::DrawMode]->trigger(); + m_document->addLayerToView(pane, newLayer1); + m_paneStack->setCurrentLayer(pane, newLayer); + + //editCurrentLayer(); + + //text decoder + unsigned char dat,dat1,dat2,dat3; + FILE *imf; + imf = fopen (filename.toStdString().c_str(),"rb"); + + fseek (imf,0,SEEK_SET); + fseek (imf,24,SEEK_CUR); //jump to 'mdat' + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + int sizemdat = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + fseek(imf, sizemdat-4, SEEK_CUR); // -4 because we have to sub the 4 bytes of size + + fseek (imf,16,SEEK_CUR); + fseek (imf,96,SEEK_CUR); // next track id is placed 96 bytes after the last byte of type 'mvhd' + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + + audiotracks = ((dat<<24) | (dat1<<16) | (dat2<<8) | (dat3)) -1 ; //read the number of audio tracks.It is ´-1´ because the field indicates the number of tracks +1 + + fread(&dat, sizeof(unsigned char), 1, imf);//read the size of trak.Every track must be the same size + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + int sizetrak = ((dat<<24) | (dat1<<16) | (dat2<<8) | (dat3)); + + fseek(imf, (sizetrak-4)*audiotracks, SEEK_CUR); + + int d=0; + while (d==0){ + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + + if (dat == 0x73 && dat1 == 0x74 && dat2 == 0x74 && dat3 == 0x73) { // 73 74 74 73 = s t t s + d=1; + } + + else{ + fseek(imf, -3, SEEK_CUR); //if we have not readen ´stts´ + } + + } //close while + + fread(&dat, sizeof(unsigned char), 1, imf);//avanzamos 4 bytes (son los 4 bytes de version) + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat, sizeof(unsigned char), 1, imf); + + fread(&dat, sizeof(unsigned char), 1, imf);//estos 4 bytes son los de número de entradas de la tabla (entry_count) + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + int entry_count = ((dat<<24) | (dat1<<16) | (dat2<<8) | (dat3)); + + int sample_count [entry_count]; + int sample_delta [entry_count]; + + for (int i=0;i1){ //sizestring = 1 when there is only a blank space.We do not want to add a blank space alone. + + if (samplecount%2==0){//to avoid overlapping + m_paneStack->setCurrentLayer(pane, newLayer); + insertLyrics (duration3, result); + } + else{ + m_paneStack->setCurrentLayer(pane, newLayer1); + insertLyrics (duration3, result); + } + + + } // close if + } //close for + } // close if haslyrics + +} +void +MainWindow::openMP3IMAF() +{ + FileOpenStatus status; + + for (int i=0;iobjectName().toInt(); + + if( (selrule_type == 0) || (selrule_type == 1) || (selrule_type == 3) ){ + sel_rule1->setText("Track A"); + sel_rule1->setDisabled(false); + sel_rule2->setText("Track B"); + sel_rule2->setDisabled(false); + }else{ + sel_rule1->setText("Track A"); + sel_rule1->setDisabled(false); + sel_rule2->setDisabled(true); + } +} + +void CheckBox::set_selrulePAR1(int value) +{ + selrule_par1 = value; // TRACK A +} + +void CheckBox::set_selrulePAR2(int value) +{ + selrule_par2 = value; // TRACK B +} + +void CheckBox::set_mixruleType(QAbstractButton *button) +{ + mixrule_type = button->objectName().toInt(); + + if( (mixrule_type == 0) || (mixrule_type == 1) || (mixrule_type == 2) ){ + mix_rule1->setText("Track A"); + mix_rule1->setDisabled(false); + mix_rule2->setText("Track B"); + mix_rule2->setDisabled(false); + mix_rule3->setDisabled(true); + mix_rule4->setDisabled(true); + }else{ + mix_rule1->setText("Track A"); + mix_rule1->setDisabled(false); + mix_rule2->setDisabled(true); + mix_rule3->setText("Min Volume"); + mix_rule3->setDisabled(false); + mix_rule4->setText("Max Volume"); + mix_rule4->setDisabled(false); + } +} + +void CheckBox::set_mixrulePAR1(int value) +{ + mixrule_par1 = value; // TRACK A +} + +void CheckBox::set_mixrulePAR2(int value) +{ + mixrule_par2 = value; // TRACK B +} + +void CheckBox::set_mixrulePAR3(int value) +{ + mixrule_par3 = value; // MIN VOL for Limit Rule +} + +void CheckBox::set_mixrulePAR4(int value) +{ + mixrule_par4 = value; // MAX VOL for Limit Rule +} + +void CheckBox::set_TrackInGroup(QAbstractButton *button) +{ + int temp = button->objectName().toInt(); + + if (button->isChecked()){ + group_tracks[temp-1] = 1; + }else{ + group_tracks[temp-1] = 0; + } +} + +void CheckBox::set_GroupName(QString name) +{ + group_name = name; +} + +void CheckBox::set_GroupVolume(int value) +{ + group_volume = value; +} + +void CheckBox::set_presetType(QAbstractButton *button) +{ + preset_type = button->objectName().toInt(); +} + +void CheckBox::set_fade(QAbstractButton *button) +{ + fade_in = button->objectName().toInt(); +} diff -r 66ef06a6d591 -r e3a4831f9c64 main/MainWindow.h --- a/main/MainWindow.h Tue Nov 05 11:14:16 2013 +0000 +++ b/main/MainWindow.h Tue Nov 05 11:17:35 2013 +0000 @@ -5,7 +5,7 @@ An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2006-2007 Chris Cannam and QMUL. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the @@ -60,7 +60,6 @@ class ActivityLog; class QFileSystemWatcher; class QScrollArea; -class VersionTester; class MainWindow : public MainWindowBase { @@ -188,13 +187,17 @@ virtual void about(); virtual void keyReference(); virtual void newerVersionAvailable(QString); + virtual void exportIMAF(); + virtual void importIMAF(); + virtual void openMP3IMAF(); + virtual void insertLyrics(size_t frame, QString text); protected: Overview *m_overview; Fader *m_fader; AudioDial *m_playSpeed; WaveformLayer *m_panLayer; - + QScrollArea *m_mainScroll; bool m_mainMenusCreated; @@ -248,17 +251,15 @@ QFileSystemWatcher *m_templateWatcher; - VersionTester *m_versionTester; - struct LayerConfiguration { - LayerConfiguration(LayerFactory::LayerType _layer - = LayerFactory::TimeRuler, + LayerConfiguration(LayerFactory::LayerType _layer + = LayerFactory::TimeRuler, Model *_source = 0, int _channel = -1) : - layer(_layer), sourceModel(_source), channel(_channel) { } - LayerFactory::LayerType layer; + layer(_layer), sourceModel(_source), channel(_channel) { } + LayerFactory::LayerType layer; Model *sourceModel; - int channel; + int channel; }; typedef std::map PaneActionMap; @@ -304,7 +305,7 @@ virtual void updatePositionStatusDisplays() const; virtual bool shouldCreateNewSessionForRDFAudio(bool *cancel); - + virtual void connectLayerEditDialog(ModelDataTableDialog *); }; diff -r 66ef06a6d591 -r e3a4831f9c64 main/OSCHandler.cpp --- a/main/OSCHandler.cpp Tue Nov 05 11:14:16 2013 +0000 +++ b/main/OSCHandler.cpp Tue Nov 05 11:17:35 2013 +0000 @@ -5,7 +5,7 @@ An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2006-2007 Chris Cannam and QMUL. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the @@ -35,7 +35,7 @@ void MainWindow::handleOSCMessage(const OSCMessage &message) { - SVDEBUG << "MainWindow::handleOSCMessage: thread id = " + SVDEBUG << "MainWindow::handleOSCMessage: thread id = " << QThread::currentThreadId() << endl; // This large function should really be abstracted out. @@ -154,7 +154,7 @@ if (play) { m_viewManager->setPlaySelectionMode(selection); - } + } if (selection) { MultiSelection::SelectionList sl = m_viewManager->getSelections(); @@ -199,7 +199,7 @@ } } else if (message.getMethod() == "stop") { - + if (m_playSource->isPlaying()) m_playSource->stop(); } else if (message.getMethod() == "loop") { @@ -241,7 +241,7 @@ if (message.getArgCount() == 2 && message.getArg(0).canConvert(QVariant::Double) && message.getArg(1).canConvert(QVariant::Double)) { - + double t0 = message.getArg(0).toDouble(); double t1 = message.getArg(1).toDouble(); if (t1 < t0) { double temp = t0; t0 = t1; t1 = temp; } @@ -250,7 +250,7 @@ f0 = lrint(t0 * getMainModel()->getSampleRate()); f1 = lrint(t1 * getMainModel()->getSampleRate()); - + Pane *pane = m_paneStack->getCurrentPane(); Layer *layer = 0; if (pane) layer = pane->getSelectedLayer(); @@ -301,7 +301,7 @@ } QString str = message.getArg(0).toString(); - + LayerFactory::LayerType type = LayerFactory::getInstance()->getLayerTypeForName(str); @@ -313,7 +313,7 @@ LayerConfiguration configuration(type, getMainModel(), channel); - + addPane(configuration, tr("Add %1 Pane") .arg(LayerFactory::getInstance()-> @@ -352,7 +352,7 @@ m_viewManager->setOverlayMode(ViewManager::MinimalOverlays); } else { m_viewManager->setOverlayMode(ViewManager::AllOverlays); - } + } } else if (property == "zoomwheels") { m_viewManager->setZoomWheelsEnabled(value > 0.5); } else if (property == "propertyboxes") { @@ -360,7 +360,7 @@ (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks)); if (toggle) togglePropertyBoxes(); } - + } else { PropertyContainer *container = 0; Pane *pane = m_paneStack->getCurrentPane(); @@ -416,7 +416,7 @@ if (message.getArgCount() == 1 && message.getArg(0).canConvert(QVariant::String)) { - + QString target = message.getArg(0).toString(); if (target == "pane") { @@ -428,7 +428,7 @@ deleteCurrentLayer(); } else { - + std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown delete target " << target << std::endl; } } @@ -491,12 +491,12 @@ } } else if (message.getMethod() == "quit") { - + m_abandoning = true; close(); } else if (message.getMethod() == "resize") { - + if (message.getArgCount() == 2) { int width = 0, height = 0; @@ -530,9 +530,9 @@ TransformId transformId = message.getArg(0).toString(); - Transform transform = TransformFactory::getInstance()-> + Transform transform = TransformFactory::getInstance()-> getDefaultTransformFor(transformId); - + Layer *newLayer = m_document->createDerivedLayer (transform, getMainModel()); @@ -548,5 +548,5 @@ << "method \"" << message.getMethod().toStdString() << "\"" << std::endl; } - + } diff -r 66ef06a6d591 -r e3a4831f9c64 main/PreferencesDialog.cpp --- a/main/PreferencesDialog.cpp Tue Nov 05 11:14:16 2013 +0000 +++ b/main/PreferencesDialog.cpp Tue Nov 05 11:17:35 2013 +0000 @@ -5,7 +5,7 @@ An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2006 Chris Cannam. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the @@ -56,7 +56,7 @@ m_tabs = new QTabWidget; grid->addWidget(m_tabs, 0, 0); - + m_tabs->setTabPosition(QTabWidget::North); // Create this first, as slots that get called from the ctor will @@ -77,7 +77,7 @@ this, SLOT(windowTypeChanged(WindowType))); QComboBox *smoothing = new QComboBox; - + int sm = prefs->getPropertyRangeAndValue("Spectrogram Y Smoothing", &min, &max, &deflt); m_spectrogramSmoothing = sm; @@ -92,7 +92,7 @@ this, SLOT(spectrogramSmoothingChanged(int))); QComboBox *xsmoothing = new QComboBox; - + int xsm = prefs->getPropertyRangeAndValue("Spectrogram X Smoothing", &min, &max, &deflt); m_spectrogramXSmoothing = xsm; @@ -136,7 +136,7 @@ QComboBox *audioDevice = new QComboBox; std::vector devices = AudioTargetFactory::getInstance()->getCallbackTargetNames(); - + QSettings settings; settings.beginGroup("Preferences"); QString targetName = settings.value("audio-target", "").toString(); @@ -233,7 +233,7 @@ // General tab QFrame *frame = new QFrame; - + QGridLayout *subgrid = new QGridLayout; frame->setLayout(subgrid); @@ -260,7 +260,7 @@ subgrid->addWidget(resampleQuality, row++, 1, 1, 2); subgrid->setRowStretch(row, 10); - + m_tabOrdering[GeneralTab] = m_tabs->count(); m_tabs->addTab(frame, tr("&General")); @@ -299,7 +299,7 @@ subgrid->addWidget(showSplash, row++, 1, 1, 1); subgrid->setRowStretch(row, 10); - + m_tabOrdering[AppearanceTab] = m_tabs->count(); m_tabs->addTab(frame, tr("&Appearance")); @@ -331,9 +331,9 @@ subgrid->addWidget(m_windowTypeSelector, row++, 1, 2, 2); subgrid->setRowStretch(row, 10); row++; - + subgrid->setRowStretch(row, 10); - + m_tabOrdering[AnalysisTab] = m_tabs->count(); m_tabs->addTab(frame, tr("Anal&ysis")); @@ -343,7 +343,7 @@ subgrid = new QGridLayout; frame->setLayout(subgrid); row = 0; - + subgrid->addWidget(new QLabel(tr("Default session template for audio files:")), row++, 0); QListWidget *lw = new QListWidget(); @@ -384,7 +384,7 @@ QDialogButtonBox *bb = new QDialogButtonBox(Qt::Horizontal); grid->addWidget(bb, 1, 0); - + QPushButton *ok = new QPushButton(tr("OK")); QPushButton *cancel = new QPushButton(tr("Cancel")); bb->addButton(ok, QDialogButtonBox::AcceptRole); @@ -550,7 +550,7 @@ prefs->setBackgroundMode(Preferences::BackgroundMode(m_backgroundMode)); prefs->setTimeToTextMode(Preferences::TimeToTextMode(m_timeToTextMode)); prefs->setViewFontSize(m_viewFontSize); - + std::vector devices = AudioTargetFactory::getInstance()->getCallbackTargetNames(); @@ -571,7 +571,7 @@ tr("Restart required

One or more of the application preferences you have changed may not take full effect until Sonic Visualiser is restarted.

Please exit and restart the application now if you want these changes to take effect immediately.

")); m_changesOnRestart = false; } -} +} void PreferencesDialog::cancelClicked() diff -r 66ef06a6d591 -r e3a4831f9c64 main/PreferencesDialog.h --- a/main/PreferencesDialog.h Tue Nov 05 11:14:16 2013 +0000 +++ b/main/PreferencesDialog.h Tue Nov 05 11:17:35 2013 +0000 @@ -5,7 +5,7 @@ An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2006 Chris Cannam. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the @@ -78,7 +78,7 @@ QString m_currentTemplate; QStringList m_templates; - + WindowType m_windowType; int m_spectrogramSmoothing; int m_spectrogramXSmoothing; diff -r 66ef06a6d591 -r e3a4831f9c64 main/checkbox.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/checkbox.h Tue Nov 05 11:17:35 2013 +0000 @@ -0,0 +1,46 @@ +#ifndef CHECKBOX_H +#define CHECKBOX_H + +#include +#include +#include +#include +#include +#include +#include "MainWindow.h" + +class CheckBox : public QWidget +{ + Q_OBJECT + +public: + CheckBox(QWidget *parent = 0); + QLineEdit *line = new QLineEdit("", this); + QLineEdit *line2 = new QLineEdit("", this); + QLabel *sel_rule1, *sel_rule2; + QLabel *mix_rule1, *mix_rule2, *mix_rule3, *mix_rule4; + QLabel *group_label, *grp_vol, *grp_name; + QLineEdit *group_name_line; + +private slots: + void defineImafTextFile(); + void defineImafImageFile(); + void saveImafFile(); + void insertLyrics(int state); + void insertImage(int state); + void set_selruleType(QAbstractButton *button); + void set_selrulePAR1(int value); + void set_selrulePAR2(int value); + void set_mixruleType(QAbstractButton *button); + void set_mixrulePAR1(int value); + void set_mixrulePAR2(int value); + void set_mixrulePAR3(int value); + void set_mixrulePAR4(int value); + void set_TrackInGroup(QAbstractButton *button); + void set_GroupName(QString name); + void set_GroupVolume(int value); + void set_presetType(QAbstractButton *button); + void set_fade(QAbstractButton *button); +}; + +#endif // CHECKBOX_H diff -r 66ef06a6d591 -r e3a4831f9c64 main/imafdecoder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/imafdecoder.cpp Tue Nov 05 11:17:35 2013 +0000 @@ -0,0 +1,212 @@ +//Jesús Corral García +//Universidad de Málaga + +#include +#include +#include +#include +#include +#include "MainWindow.h" + + +int audiotracks; //number of audio tracks contained inside the IM AF file + +int mainIMAFdecoder(QString outimaf){ + + FILE *imf,*audiotrack; + int d=0,i,j,sizemdat,audiosize; + int chunkoffset[64]; // if you want more than 64 tracks , change this value. + unsigned char dat,dat1,dat2,dat3; + QTextStream out(stdout); + + imf = fopen (outimaf.toStdString().c_str(),"rb"); + + fseek (imf,0,SEEK_SET); + fseek (imf,24,SEEK_CUR); //jump to 'mdat' + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + sizemdat = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + if (sizemdat==1){ // if conformance file + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + sizemdat = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + fseek(imf,sizemdat-16,SEEK_CUR); + } + else { + + fseek(imf, sizemdat-4, SEEK_CUR); // -4 because we have to sub the 4 bytes of size + } + + fseek (imf,16,SEEK_CUR); + fseek (imf,96,SEEK_CUR); // next track id is placed 96 bytes after the last byte of type 'mvhd' + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + audiotracks = ((dat<<24) | (dat1<<16) | (dat2<<8) | (dat3)) -1 ; //read the number of audio tracks.It is ´-1´ because the field indicates the number of tracks +1 + + + if (audiotracks == 12345678){ + + audiotracks = 6; // for the conformance file 2 + + } + for (j=1;j<=audiotracks;j++){ + + d=0; + while (d==0){ + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + + if (dat == 0x68 && dat1 == 0x64 && dat2 == 0x6C && dat3 == 0x72) { // 68646C72 = hdlr + d=1; + } + + else{ + fseek(imf, -3, SEEK_CUR); //if we have not readen ´hdlr´ + } + + } //close while + + for (i=1;i<=8;i++){ //handler type is placed eight bytes after the last byte of type 'hdlr' + + fread(&dat, sizeof(unsigned char), 1, imf); + } + + fread(&dat, sizeof(unsigned char), 1, imf);//dat could be ´s´ (soun) or ´t´(text) + + d=0; + if (dat==0x73){ //73 = ´s´ + + while (d==0){ + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + if (dat == 0x63 && dat1 == 0x6F && dat2 == 0x36 && dat3 == 0x34) { // 636F3634 = co64 + d=1; + } + else if (dat == 0x73 && dat1 == 0x74 && dat2 == 0x63 && dat3 == 0x6F){ //7374636F = stco + d=2; + } + + else{ + fseek(imf, -3, SEEK_CUR); //if we have not readen ´stco´ + } + + } //close while + if (d==1){ // if co64 + for (i=1;i<=12;i++){ + + fread(&dat, sizeof(unsigned char), 1, imf); + } + } + if (d==2){// if stco + for (i=1;i<=8;i++){ + + fread(&dat, sizeof(unsigned char), 1, imf); + } + } + + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + chunkoffset[j-1] = (dat<<24) | (dat1<<16) | (dat2<<8) | (dat3); + + + }//close if + + + } //close for +//At this point, we will look for a text track. If d=2 there are no lyrics + d=0; + while (d==0){ + + fread(&dat, sizeof(unsigned char), 1, imf); + fread(&dat1, sizeof(unsigned char), 1, imf); + fread(&dat2, sizeof(unsigned char), 1, imf); + fread(&dat3, sizeof(unsigned char), 1, imf); + + if (feof (imf )){// if end of file -> no lyrics + d=2; + } + else if (dat == 0x68 && dat1 == 0x64 && dat2 == 0x6C && dat3 == 0x72) { // 68646C72 = hdlr + d=1; + } + else{ + fseek(imf, -3, SEEK_CUR); //if we have not readen ´hdlr´ + } + + } //close while + + +// At this point, we know the position of the audio tracks in mdat and the number of tracks. +// Now we will separate the audio tracks in several MP3. + + fseek(imf, 0, SEEK_SET); + for (j=0;j