00001
00002
00003
00004
00005
00006 #include <math.h>
00007 #include <string.h>
00008 #include <stdlib.h>
00009 #include "SongItem.h"
00010
00011
00012
00013
00014 TSongItem::TSongItem()
00015 {
00016 start = 0;
00017 note = NULL;
00018 mid = NULL;
00019 noteIndex = NULL;
00020 refrainIndex = NULL;
00021 midRefrainIndex = NULL;
00022 noteSize = midSize = noteIndexSize = refrainIndexSize = 0;
00023 score = 0.0;
00024 Fields = new TMyStringList();
00025 }
00026
00027
00028
00029
00030 TSongItem::~TSongItem()
00031 {
00032 delete[] note;
00033 FreeMid();
00034 FreeRefrain();
00035 delete Fields;
00036 }
00037
00048
00049
00050
00051
00052 void TSongItem::SetProperty(char *line)
00053 {
00054
00055 char *token, *value, *refStr;
00056 int ref[100], len;
00057
00058 if (line == NULL)
00059 return;
00060
00061
00062 refStr = NULL;
00063 len = strlen(line);
00064 if (line[len - 1] == '\n')
00065 line[len - 1] = '\0';
00066
00067 token = strtok(line, "\t");
00068 while (token)
00069 {
00070 if ((value = strchr(token, '=')) != NULL)
00071 {
00072 value++;
00073 if (*value != '\0' && *value != ' ')
00074 {
00075 if (!strncmp(token, "start=", 6))
00076 start = atoi(value);
00077 else if (!strncmp(token, "size=", 5))
00078 noteSize = atoi(value);
00079 else if (!strncmp(token, "refrain=", 8))
00080 {
00081
00082 delete[] refStr;
00083 refStr = new char[strlen(value) + 1];
00084 strcpy(refStr, value);
00085
00086 }
00087 else
00088
00089 Fields->Add(token);
00090 }
00091 }
00092 token = strtok(NULL, "\t");
00093 }
00094
00095 if (refStr != NULL)
00096 {
00097 token = strtok(refStr, "+");
00098
00099 while (token)
00100 {
00101
00102
00103 ref[refrainIndexSize++] = atoi(token) * 2;
00104 token = strtok(NULL, "+");
00105 }
00106 delete[] refStr;
00107 refrainIndex = new int[refrainIndexSize];
00108 memcpy(refrainIndex, ref, refrainIndexSize * sizeof(int));
00109 }
00110 }
00111
00122
00123
00124
00125
00126
00127
00128
00129 bool TSongItem::Read(TInputStream *DbStream, int resampleRate)
00130 {
00131 unsigned char uc;
00132 delete[] note;
00133 note = new unsigned char[noteSize];
00134 DbStream->Reset();
00135
00136 DbStream->Skip(start);
00137 DbStream->Reads(note, noteSize);
00138 uc = DbStream->Read();
00139 if (uc != 0xFF){
00140 return false;
00141 }
00142
00143 Ready(resampleRate);
00144 return true;
00145 }
00146
00154
00155
00156
00157
00158 void TSongItem::Write(TOutputStream *IndexStream, TOutputStream *DbStream)
00159 {
00160 char str[100];
00161 int i, j;
00162 unsigned char *encodedNote;
00163
00164 start = DbStream->Size();
00165 sprintf(str, "start=%d\tsize=%d", start, noteSize);
00166 IndexStream->Writes(str, strlen(str));
00167 for (i = 0; i < Fields->count; i++)
00168 {
00169 sprintf(str, "\t%s", Fields->Strings(i));
00170 IndexStream->Writes(str, strlen(str));
00171 }
00172 if (refrainIndexSize > 0)
00173 {
00174 sprintf(str, "\trefrain=%d", refrainIndex[0]);
00175 IndexStream->Writes(str, strlen(str));
00176 for (i = 1; i < refrainIndexSize; i++)
00177 {
00178 sprintf(str, "+%d", refrainIndex[i]);
00179 IndexStream->Writes(str, strlen(str));
00180 }
00181 }
00182 IndexStream->Write('\n');
00183 DbStream->Writes(note, noteSize);
00184 DbStream->Write(0xFF);
00185 }
00196
00197
00198
00199
00200
00201
00202 void TSongItem::NoteToMid(int resampleRate, int scale)
00203 {
00204
00205 int i, j, k, size;
00206
00207
00208
00209 delete[] mid;
00210 mid = new int[midSize];
00211 delete[] noteIndex;
00212
00213
00214 noteIndex = new int[noteIndexSize];
00215
00216
00217 for (i = 0, j = -1, k = 0, size = 0; i < midSize; i++)
00218 {
00219
00220
00221
00222
00223 while (size <= i * resampleRate)
00224 {
00225 size += note[j += 2];
00226 if (k < noteIndexSize && note[j - 1] != 0)
00227 noteIndex[k++] = i;
00228
00229
00230 }
00231
00232
00233 mid[i] = note[j - 1] * scale;
00234
00235
00236 }
00237
00238 }
00243
00244
00245
00246 void TSongItem::FreeMid(void)
00247 {
00248 delete[] mid;
00249 mid = NULL;
00250 delete[] noteIndex;
00251 noteIndex = NULL;
00252 }
00257
00258
00259
00260 void TSongItem::FreeRefrain(void)
00261 {
00262 refrainIndexSize = 0;
00263 delete[] refrainIndex;
00264 refrainIndex = NULL;
00265 delete[] midRefrainIndex;
00266 midRefrainIndex = NULL;
00267 }
00272
00273
00274
00275 void TSongItem::Ready(int resampleRate)
00276 {
00277 int i, j, k, size;
00278
00279
00280
00281 for (i = 1, midSize = 0; i < noteSize; i += 2)
00282 midSize += note[i];
00283 midSize /= resampleRate;
00284
00285
00286
00287
00288
00289
00290 for (j = noteSize - 1, size = 0; j >= 1; j -= 2)
00291 if ((size += note[j]) >= (SEGMENT_SIZE + 1) * resampleRate)
00292 break;
00293
00294
00295
00296 if (size >= (SEGMENT_SIZE + 1) * resampleRate)
00297 for (i = 0, noteIndexSize = 0; i < j; i += 2)
00298 if (note[i] != 0)
00299 noteIndexSize++;
00300
00301 if (noteSize > 0)
00302 {
00303 delete[] midRefrainIndex;
00304 midRefrainIndex = new int[refrainIndexSize + 1];
00305
00306 midRefrainIndex[0] = 0;
00307 for (i = 0, j = -1, k = 0, size = 0; k < refrainIndexSize; i++)
00308 while (size <= i * resampleRate)
00309 {
00310 size += note[j += 2];
00311
00312
00313 if (refrainIndex[k] == j - 1)
00314 {
00315 midRefrainIndex[++k] = i;
00316 if (k >= refrainIndexSize)
00317 break;
00318 }
00319 }
00320 }
00321 }
00322