diff options
Diffstat (limited to 'src/lib/hd24transferengine.cpp')
-rw-r--r-- | src/lib/hd24transferengine.cpp | 2143 |
1 files changed, 2143 insertions, 0 deletions
diff --git a/src/lib/hd24transferengine.cpp b/src/lib/hd24transferengine.cpp new file mode 100644 index 0000000..32db2d8 --- /dev/null +++ b/src/lib/hd24transferengine.cpp | |||
@@ -0,0 +1,2143 @@ | |||
1 | #include "hd24transferengine.h" | ||
2 | #include <config.h> | ||
3 | #include <hd24fs.h> | ||
4 | #include <hd24sndfile.h> | ||
5 | |||
6 | #define HD24TRANSFERDEBUG 0 | ||
7 | #define MAXCHANNELS 24 | ||
8 | #define TRACKACTION_UNDEF -1 | ||
9 | |||
10 | hd24transferjob::hd24transferjob() | ||
11 | { | ||
12 | #if (HD24TRANSFERDEBUG==1) | ||
13 | cout << "hd24transferjob::hd24transferjob();" << endl; | ||
14 | #endif | ||
15 | init_vars(); | ||
16 | } | ||
17 | |||
18 | hd24transferjob::~hd24transferjob() | ||
19 | { | ||
20 | #if (HD24TRANSFERDEBUG==1) | ||
21 | cout << "hd24transferjob::~hd24transferjob();" << endl; | ||
22 | #endif | ||
23 | |||
24 | if (trackselected!=NULL) | ||
25 | { | ||
26 | delete trackselected; | ||
27 | trackselected=NULL; | ||
28 | } | ||
29 | usecustomrate=0; // by default, match export samrate with song rate | ||
30 | if (m_projectdir!=NULL) | ||
31 | { | ||
32 | delete m_projectdir; | ||
33 | m_projectdir=NULL; | ||
34 | } | ||
35 | } | ||
36 | |||
37 | void hd24transferjob::init_vars() | ||
38 | { | ||
39 | #if (HD24TRANSFERDEBUG==1) | ||
40 | cout << "hd24transferjob::init_vars()" << endl; | ||
41 | #endif | ||
42 | this->wantsplit=1; | ||
43 | trackselected=new int[MAXCHANNELS]; | ||
44 | for (int i=0;i<MAXCHANNELS;i++) | ||
45 | { | ||
46 | trackselected[i]=0; | ||
47 | } | ||
48 | m_projectdir=NULL; | ||
49 | llsizelimit=1024*1024*1024; | ||
50 | mixleft=0; | ||
51 | mixright=0; | ||
52 | m_selectedformat=0; | ||
53 | usecustomrate=0; | ||
54 | stamprate=48000; | ||
55 | wantsplit=1; | ||
56 | |||
57 | jobsourcesong=NULL; | ||
58 | jobtargetsong=NULL; | ||
59 | jobsourcefs=NULL; | ||
60 | jobtargetfs=NULL; | ||
61 | have_smpte=false; | ||
62 | |||
63 | m_startoffset=0; | ||
64 | m_endoffset=0; | ||
65 | for (int i=0;i<24;i++) | ||
66 | { | ||
67 | this->filepath[i]=NULL; | ||
68 | this->filehandle[i]=NULL; | ||
69 | this->m_trackaction[i]=TRACKACTION_UNDEF; // undefined trackaction | ||
70 | } | ||
71 | return; | ||
72 | } | ||
73 | |||
74 | void hd24transferjob::trackaction(int base1tracknum,int action) | ||
75 | { | ||
76 | #if (HD24TRANSFERDEBUG==1) | ||
77 | cout << "hd24transferjob::trackaction(base1track=" | ||
78 | << base1tracknum << ", action=" << action << ")" << endl; | ||
79 | #endif | ||
80 | |||
81 | m_trackaction[base1tracknum-1]=action; | ||
82 | } | ||
83 | |||
84 | int hd24transferjob::trackaction(int base1tracknum) | ||
85 | { | ||
86 | #if (HD24TRANSFERDEBUG==1) | ||
87 | cout << "returning hd24transferjob::trackaction(base1track=" | ||
88 | << base1tracknum << ")=" << m_trackaction[base1tracknum-1] | ||
89 | << endl; | ||
90 | #endif | ||
91 | return m_trackaction[base1tracknum-1]; | ||
92 | } | ||
93 | |||
94 | void hd24transferengine::trackaction(int base1tracknum,int action) | ||
95 | { | ||
96 | job->trackaction(base1tracknum,action); | ||
97 | } | ||
98 | |||
99 | int hd24transferengine::trackaction(int base1tracknum) | ||
100 | { | ||
101 | return job->trackaction(base1tracknum); | ||
102 | } | ||
103 | |||
104 | char* hd24transferjob::sourcefilename(int base1tracknum) | ||
105 | { | ||
106 | if (base1tracknum<1) return NULL; | ||
107 | if (base1tracknum>24) return NULL; | ||
108 | return filepath[base1tracknum-1]; | ||
109 | } | ||
110 | |||
111 | void hd24transferjob::sourcefilename(int base1tracknum,const char* filename) | ||
112 | { | ||
113 | /* set nth filename to the given char string */ | ||
114 | if (base1tracknum<1) return; | ||
115 | if (base1tracknum>24) return; | ||
116 | |||
117 | if (filepath[base1tracknum-1]!=NULL) | ||
118 | { | ||
119 | free(filepath[base1tracknum-1]); | ||
120 | } | ||
121 | __uint32 n=strlen(filename); | ||
122 | char* tmpbuf=(char*)malloc(n); | ||
123 | filepath[base1tracknum-1]=tmpbuf; | ||
124 | strncpy(tmpbuf,filename,n+1); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | void hd24transferengine::sourcefilename(int base1tracknum,const char* filename) | ||
129 | { | ||
130 | job->sourcefilename(base1tracknum,filename); | ||
131 | } | ||
132 | |||
133 | char* hd24transferengine::sourcefilename(int base1tracknum) | ||
134 | { | ||
135 | return job->sourcefilename(base1tracknum); | ||
136 | } | ||
137 | |||
138 | void hd24transferjob::startoffset(__uint32 newoff) | ||
139 | { | ||
140 | m_startoffset=newoff; | ||
141 | } | ||
142 | |||
143 | void hd24transferjob::endoffset(__uint32 newoff) | ||
144 | { | ||
145 | m_endoffset=newoff; | ||
146 | } | ||
147 | |||
148 | __uint32 hd24transferjob::startoffset() | ||
149 | { | ||
150 | return m_startoffset; | ||
151 | } | ||
152 | |||
153 | __uint32 hd24transferjob::endoffset() | ||
154 | { | ||
155 | return m_endoffset; | ||
156 | } | ||
157 | |||
158 | hd24fs* hd24transferjob::sourcefs() | ||
159 | { | ||
160 | return this->jobsourcefs; | ||
161 | } | ||
162 | |||
163 | hd24song* hd24transferjob::sourcesong() | ||
164 | { | ||
165 | return this->jobsourcesong; | ||
166 | } | ||
167 | |||
168 | void hd24transferjob::sourcefs(hd24fs* fs) | ||
169 | { | ||
170 | this->jobsourcefs=fs; | ||
171 | } | ||
172 | |||
173 | void hd24transferjob::sourcesong(hd24song* song) | ||
174 | { | ||
175 | this->jobsourcesong=song; | ||
176 | this->jobsourcefs=jobsourcesong->parentfs; | ||
177 | } | ||
178 | |||
179 | hd24fs* hd24transferjob::targetfs() | ||
180 | { | ||
181 | return this->jobtargetfs; | ||
182 | } | ||
183 | |||
184 | hd24song* hd24transferjob::targetsong() | ||
185 | { | ||
186 | return this->jobtargetsong; | ||
187 | } | ||
188 | |||
189 | void hd24transferjob::targetfs(hd24fs* fs) | ||
190 | { | ||
191 | this->jobtargetfs=fs; | ||
192 | } | ||
193 | |||
194 | void hd24transferjob::targetsong(hd24song* song) | ||
195 | { | ||
196 | this->jobtargetsong=song; | ||
197 | this->jobtargetfs=jobtargetsong->parentfs; | ||
198 | } | ||
199 | |||
200 | void hd24transferjob::projectdir(const char* projdir) | ||
201 | { | ||
202 | #if (HD24TRANSFERDEBUG==1) | ||
203 | cout << "hd24transferjob::projectdir("<<projdir<< ")"<<endl; | ||
204 | #endif | ||
205 | if (m_projectdir!=NULL) | ||
206 | { | ||
207 | delete m_projectdir; | ||
208 | m_projectdir=NULL; | ||
209 | } | ||
210 | m_projectdir=new string(projdir); | ||
211 | return; | ||
212 | } | ||
213 | |||
214 | const char* hd24transferjob::projectdir() | ||
215 | { | ||
216 | #if (HD24TRANSFERDEBUG==1) | ||
217 | cout << "returning hd24transferjob::projectdir()="; | ||
218 | if (m_projectdir==NULL) | ||
219 | { | ||
220 | cout <<" NULL " << endl; | ||
221 | } else { | ||
222 | cout <<*m_projectdir<<endl; | ||
223 | } | ||
224 | #endif | ||
225 | return m_projectdir->c_str(); | ||
226 | } | ||
227 | |||
228 | void hd24transferengine::lasterror(const char* errormessage) | ||
229 | { | ||
230 | if (m_lasterror!=NULL) | ||
231 | { | ||
232 | delete m_lasterror; | ||
233 | } | ||
234 | m_lasterror=new string(errormessage); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | string* hd24transferengine::lasterror() | ||
239 | { | ||
240 | return m_lasterror; | ||
241 | } | ||
242 | |||
243 | |||
244 | int hd24transferengine::format_outputchannels(int format) | ||
245 | { | ||
246 | return m_format_outputchannels[format]; | ||
247 | } | ||
248 | |||
249 | const char* hd24transferengine::projectdir() | ||
250 | { | ||
251 | cout << "returning hd24transferengine::projectdir()"<<endl; | ||
252 | return job->projectdir(); | ||
253 | } | ||
254 | |||
255 | void hd24transferengine::projectdir(const char* projdir) | ||
256 | { | ||
257 | #if (HD24TRANSFERDEBUG==1) | ||
258 | cout << "hd24transferengine::projectdir("<<projdir<< ")"<<endl; | ||
259 | #endif | ||
260 | job->projectdir(projdir); | ||
261 | return; | ||
262 | } | ||
263 | |||
264 | hd24transferengine::hd24transferengine() | ||
265 | { | ||
266 | #if (HD24TRANSFERDEBUG==1) | ||
267 | cout <<"hd24transferengine::hd24transferengine()" << endl; | ||
268 | #endif | ||
269 | init_vars(); | ||
270 | } | ||
271 | |||
272 | hd24transferengine::~hd24transferengine() | ||
273 | { | ||
274 | #if (HD24TRANSFERDEBUG==1) | ||
275 | cout <<"hd24transferengine::~hd24transferengine()" << endl; | ||
276 | #endif | ||
277 | if (m_lasterror!=NULL) | ||
278 | { | ||
279 | delete m_lasterror; | ||
280 | m_lasterror=NULL; | ||
281 | } | ||
282 | if (job!=NULL) | ||
283 | { | ||
284 | delete job; | ||
285 | job=NULL; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | void hd24transferengine::init_vars() | ||
290 | { | ||
291 | songnum=0; | ||
292 | totsongs=0; | ||
293 | ui=NULL; | ||
294 | totbytestotransfer=0; | ||
295 | totbytestransferred=0; | ||
296 | prefix=0; | ||
297 | transfer_cancel=0; | ||
298 | trackspergroup=0; | ||
299 | transfermixer=NULL; | ||
300 | job=NULL; | ||
301 | m_lasterror=NULL; | ||
302 | job=new hd24transferjob(); | ||
303 | this->uiconfirmfunction=NULL; | ||
304 | this->setstatusfunction=NULL; | ||
305 | soundfile=NULL; | ||
306 | #if (HD24TRANSFERDEBUG==1) | ||
307 | cout << "hd24transferengine::init_vars() - job="<<job<<endl; | ||
308 | #endif | ||
309 | m_format_outputextension=new vector<string>; | ||
310 | m_format_shortdesc=new vector<string>; | ||
311 | populate_formatlist(); | ||
312 | } | ||
313 | |||
314 | void hd24transferengine::populate_formatlist() | ||
315 | { | ||
316 | #if (HD24TRANSFERDEBUG==1) | ||
317 | cout << "hd24transferengine::populate_formatlist()" << endl; | ||
318 | #endif | ||
319 | /* Set up transfer format list */ | ||
320 | formatcount=0; | ||
321 | m_format_shortdesc->push_back("WAV (24 bit), mono"); | ||
322 | m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE; | ||
323 | m_format_outputchannels[formatcount]=1; // mono | ||
324 | m_format_bitdepth[formatcount]=24; | ||
325 | m_format_sndfile[formatcount]=false; // do not use libsndfile for this file format. | ||
326 | m_format_outputextension->push_back(".wav"); | ||
327 | formatcount++; | ||
328 | |||
329 | m_format_shortdesc->push_back("WAV (24 bit), stereo"); | ||
330 | m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE; | ||
331 | m_format_outputchannels[formatcount]=2; // stereo | ||
332 | m_format_bitdepth[formatcount]=24; | ||
333 | m_format_sndfile[formatcount]=true; | ||
334 | m_format_outputextension->push_back(".wav"); | ||
335 | formatcount++; | ||
336 | |||
337 | m_format_shortdesc->push_back("WAV (24 bit), multi"); | ||
338 | m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE; | ||
339 | m_format_outputchannels[formatcount]=0; // multi | ||
340 | m_format_bitdepth[formatcount]=24; | ||
341 | m_format_sndfile[formatcount]=true; | ||
342 | m_format_outputextension->push_back(".wav"); | ||
343 | formatcount++; | ||
344 | |||
345 | m_format_shortdesc->push_back("AIF (24 bit), mono"); | ||
346 | m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24; | ||
347 | m_format_outputchannels[formatcount]=1; // mono | ||
348 | m_format_bitdepth[formatcount]=24; | ||
349 | m_format_sndfile[formatcount]=false; | ||
350 | m_format_outputextension->push_back(".aif"); | ||
351 | formatcount++; | ||
352 | |||
353 | m_format_shortdesc->push_back("AIF (24 bit), stereo"); | ||
354 | m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24; | ||
355 | m_format_outputchannels[formatcount]=2; // stereo | ||
356 | m_format_bitdepth[formatcount]=24; | ||
357 | m_format_sndfile[formatcount]=true; | ||
358 | m_format_outputextension->push_back(".aif"); | ||
359 | formatcount++; | ||
360 | |||
361 | m_format_shortdesc->push_back("AIF (24 bit), multi"); | ||
362 | m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24; | ||
363 | m_format_outputchannels[formatcount]=0; // stereo | ||
364 | m_format_bitdepth[formatcount]=24; | ||
365 | m_format_sndfile[formatcount]=true; | ||
366 | m_format_outputextension->push_back(".aif"); | ||
367 | formatcount++; | ||
368 | selectedformat(0); | ||
369 | } | ||
370 | |||
371 | const char* hd24transferengine::getformatdesc(int formatnum) | ||
372 | { | ||
373 | return ((*m_format_shortdesc)[formatnum]).c_str(); | ||
374 | } | ||
375 | |||
376 | int hd24transferengine::supportedformatcount() | ||
377 | { | ||
378 | return formatcount; | ||
379 | } | ||
380 | |||
381 | void hd24transferengine::trackselected(__uint32 base0tracknum,bool selected) | ||
382 | { | ||
383 | if (base0tracknum<0) return; | ||
384 | if (base0tracknum>=MAXCHANNELS) return; | ||
385 | |||
386 | if (selected) | ||
387 | { | ||
388 | job->trackselected[base0tracknum]=1; | ||
389 | } else { | ||
390 | job->trackselected[base0tracknum]=0; | ||
391 | } | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | bool hd24transferengine::trackselected(__uint32 base0tracknum) | ||
396 | { | ||
397 | if (base0tracknum<0) return false; | ||
398 | if (base0tracknum>=MAXCHANNELS) return false; | ||
399 | |||
400 | return ((job->trackselected[base0tracknum])==1); | ||
401 | } | ||
402 | |||
403 | |||
404 | void hd24transferengine::openbuffers(unsigned char** audiobuf, | ||
405 | unsigned int channels, | ||
406 | unsigned int bufsize) | ||
407 | { | ||
408 | #if (HD24TRANSFERDEBUG==1) | ||
409 | cout << "hd24transferengine::openbuffers" << endl; | ||
410 | #endif | ||
411 | |||
412 | for (unsigned int handle=0;handle<channels;handle++) | ||
413 | { | ||
414 | if (!trackselected(handle)) { | ||
415 | // channel not selected for export | ||
416 | continue; | ||
417 | } | ||
418 | audiobuf[handle]= | ||
419 | (unsigned char *)memutils::mymalloc("openbuffers", | ||
420 | bufsize,1); | ||
421 | } | ||
422 | #if (HD24TRANSFERDEBUG==1) | ||
423 | cout << "opened buffers" << endl; | ||
424 | #endif | ||
425 | } | ||
426 | |||
427 | void hd24transferengine::closebuffers(unsigned char** audiobuf,unsigned int channels) | ||
428 | { | ||
429 | #if (HD24TRANSFERDEBUG==1) | ||
430 | cout << "hd24transferengine::closebuffers" << endl; | ||
431 | #endif | ||
432 | for (__uint32 handle=0;handle<channels;handle++) | ||
433 | { | ||
434 | if (!trackselected(handle)) { | ||
435 | // channel not selected for export | ||
436 | continue; | ||
437 | } | ||
438 | if (audiobuf[handle]!=NULL) | ||
439 | { | ||
440 | memutils::myfree("closebuffers",audiobuf[handle]); | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | |||
445 | void hd24transferengine::writerawbuf(hd24sndfile* filehandle,unsigned char* buf,long subblockbytes) | ||
446 | { | ||
447 | #if (HD24TRANSFERDEBUG==2) | ||
448 | cout << "writerawbuf (filehandle="<<filehandle<<", buf="<<buf<<", subblockbytes="<<subblockbytes<<endl; | ||
449 | #endif | ||
450 | filehandle->writerawbuf(buf,subblockbytes); | ||
451 | #if (HD24TRANSFERDEBUG==2 ) | ||
452 | cout << "end writerawbuf (filehandle="<<filehandle<<", buf="<<buf<<", subblockbytes="<<subblockbytes<<endl; | ||
453 | #endif | ||
454 | } | ||
455 | |||
456 | bool hd24transferengine::openinputfiles(SNDFILE** filehandle,SF_INFO* sfinfoin,unsigned int channels) | ||
457 | { | ||
458 | int cannotopen=0; | ||
459 | cout << "TODO: hd24transferengine::openinputfiles" << endl; | ||
460 | if (job==NULL) | ||
461 | { | ||
462 | lasterror("No job found, transfer aborted."); | ||
463 | return false; | ||
464 | } | ||
465 | |||
466 | int trackcount=0; | ||
467 | for (unsigned int handle=0;handle<channels;handle++) | ||
468 | { | ||
469 | #if (HD24TRANSFERDEBUG!=0) | ||
470 | cout << "Openinputfiles - handle=" << handle << endl; | ||
471 | #endif | ||
472 | if (job->sourcefilename(handle+1)==NULL) { | ||
473 | #if (HD24TRANSFERDEBUG!=0) | ||
474 | cout << "Channel not selected for transfer, skipping" << endl; | ||
475 | #endif | ||
476 | continue; | ||
477 | } | ||
478 | if (strlen(job->sourcefilename(handle+1))==0) { | ||
479 | #if (HD24TRANSFERDEBUG!=0) | ||
480 | cout << "Channel not selected for transfer, skipping" << endl; | ||
481 | #endif | ||
482 | continue; | ||
483 | } | ||
484 | trackcount++; | ||
485 | |||
486 | #if (HD24TRANSFERDEBUG!=0) | ||
487 | cout << "Channel selected for transfer" << endl; | ||
488 | cout << "That brings the total track count to " | ||
489 | << trackcount << endl; | ||
490 | cout << "job=" << job << endl; | ||
491 | cout << "soundfile=" << soundfile << endl; | ||
492 | cout << "sourcefilename=" << job->sourcefilename(handle+1) | ||
493 | << endl; | ||
494 | #endif | ||
495 | |||
496 | job->filehandle[handle]=soundfile->sf_open(job->sourcefilename(handle+1),SFM_READ,&sfinfoin[handle]); | ||
497 | if (!(job->filehandle[handle])) | ||
498 | { | ||
499 | cannotopen=1; | ||
500 | continue; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | return (cannotopen==0); // return true if successful, flase otherwise | ||
505 | } | ||
506 | |||
507 | bool hd24transferengine::openoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix) | ||
508 | { | ||
509 | trackspergroup=0; | ||
510 | |||
511 | SF_INFO sfinfoout; | ||
512 | bool uselibsndfile=m_format_sndfile[selectedformat()]; | ||
513 | sfinfoout.format=m_format_outputformat[selectedformat()]; | ||
514 | int chcount=0; | ||
515 | if (m_format_outputchannels[selectedformat()]==0) { | ||
516 | // count channels | ||
517 | for (unsigned int handle=0;handle<channels;handle++) | ||
518 | { | ||
519 | if (job->trackselected[handle]!=0) { | ||
520 | chcount++; | ||
521 | } | ||
522 | } | ||
523 | sfinfoout.channels=chcount; | ||
524 | } else { | ||
525 | sfinfoout.channels=m_format_outputchannels[selectedformat()]; | ||
526 | } | ||
527 | if (job->usecustomrate==1) { | ||
528 | long samrate=job->stamprate; | ||
529 | sfinfoout.samplerate=samrate; | ||
530 | } else { | ||
531 | sfinfoout.samplerate=job->sourcesong()->samplerate(); | ||
532 | } | ||
533 | // chcount and lasthandle are intended to allow | ||
534 | // support for writing multichannel files. | ||
535 | int lasthandle=0; | ||
536 | int lasttrack=-1; | ||
537 | int trackcount=0; | ||
538 | int cannotopen=0; | ||
539 | chcount=0; | ||
540 | for (unsigned int handle=0;handle<channels;handle++) | ||
541 | { | ||
542 | |||
543 | islastchanofgroup[handle]=false; | ||
544 | isfirstchanofgroup[handle]=false; | ||
545 | |||
546 | if (job->trackselected[handle]==0) { | ||
547 | // channel not selected for export | ||
548 | continue; | ||
549 | } | ||
550 | trackcount++; | ||
551 | lasttrack=handle; | ||
552 | |||
553 | string* fname=generate_filename(handle,partnum,prefix); | ||
554 | if (fname==NULL) | ||
555 | { | ||
556 | /* cannot generate filename. Most likely cause is | ||
557 | no song set */ | ||
558 | return false; // problem opening files. | ||
559 | } | ||
560 | if (chcount==0) { | ||
561 | isfirstchanofgroup[handle]=true; | ||
562 | if (uselibsndfile) | ||
563 | { | ||
564 | filehandle[handle]->sndfilehandle=NULL; | ||
565 | if (soundfile->sf_open) { | ||
566 | filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile); | ||
567 | } | ||
568 | if (!(filehandle[handle]->handle())) | ||
569 | { | ||
570 | cannotopen=1; | ||
571 | } | ||
572 | } | ||
573 | else | ||
574 | { | ||
575 | filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout); | ||
576 | } | ||
577 | lasthandle=handle; | ||
578 | } else { | ||
579 | // copy handle of previously opened file to current track | ||
580 | filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype()); | ||
581 | if (!(filehandle[handle]->handle())) | ||
582 | { | ||
583 | cannotopen=1; | ||
584 | } | ||
585 | } | ||
586 | chcount++; | ||
587 | if ((sfinfoout.channels)!=0) | ||
588 | { | ||
589 | // sfinfoout.channels=0 means full multitrack file | ||
590 | // so only a single file will be opened. | ||
591 | chcount=chcount%(sfinfoout.channels); | ||
592 | if (chcount==0) { | ||
593 | islastchanofgroup[handle]=true; | ||
594 | if (trackspergroup==0) { | ||
595 | trackspergroup=trackcount; | ||
596 | } | ||
597 | } | ||
598 | } | ||
599 | |||
600 | delete fname; | ||
601 | } | ||
602 | if (lasttrack>=0) | ||
603 | { | ||
604 | if (trackspergroup==0) { | ||
605 | trackspergroup=trackcount; | ||
606 | } | ||
607 | |||
608 | islastchanofgroup[lasttrack]=true; | ||
609 | } | ||
610 | return (cannotopen==0); // return true if successful, false otherwise | ||
611 | } | ||
612 | |||
613 | void hd24transferengine::closeinputfiles(SNDFILE** filehandle,unsigned int channels) | ||
614 | { | ||
615 | SNDFILE* lasthandle=NULL; | ||
616 | for (unsigned int handle=0;handle<channels;handle++) | ||
617 | { | ||
618 | if (job->trackselected[handle]==0) continue; | ||
619 | if (filehandle[handle]!=lasthandle) { | ||
620 | soundfile->sf_close(filehandle[handle]); | ||
621 | lasthandle=filehandle[handle]; | ||
622 | filehandle[handle]=NULL; | ||
623 | } | ||
624 | } | ||
625 | } | ||
626 | |||
627 | void hd24transferengine::closeoutputfiles(hd24sndfile** filehandle,unsigned int channels) | ||
628 | { | ||
629 | void* lasthandle=NULL; | ||
630 | |||
631 | for (unsigned int handle=0;handle<channels;handle++) | ||
632 | { | ||
633 | if (job->trackselected[handle]==0) continue; | ||
634 | if (filehandle[handle]->handle()!=lasthandle) { | ||
635 | lasthandle=(void*)filehandle[handle]->handle(); | ||
636 | if (lasthandle!=NULL) { | ||
637 | filehandle[handle]->close(); | ||
638 | } | ||
639 | } | ||
640 | } | ||
641 | } | ||
642 | |||
643 | bool hd24transferengine::confirmfileoverwrite() | ||
644 | { | ||
645 | if (this->uiconfirmfunction==NULL) | ||
646 | { | ||
647 | lasterror("Output files already exist, transfer aborted."); | ||
648 | return false; | ||
649 | } | ||
650 | |||
651 | return uiconfirmfunction(ui,"One or more output files already exist. " | ||
652 | "Do you want to overwrite them?"); | ||
653 | } | ||
654 | |||
655 | bool hd24transferengine::overwritegivesproblems(hd24song* thesong,int partnum) | ||
656 | { | ||
657 | /* this function will return TRUE if overwriting | ||
658 | existing files causes a problem, FALSE otherwise. | ||
659 | |||
660 | Overwriting files does NOT cause problems if | ||
661 | - no files are going to be overwritten | ||
662 | or | ||
663 | - Files are going to be overwritten but the user | ||
664 | permits us to do so. | ||
665 | |||
666 | */ | ||
667 | |||
668 | if (anyfilesexist(thesong)) | ||
669 | { | ||
670 | return (!(confirmfileoverwrite())); | ||
671 | } | ||
672 | return false; | ||
673 | } | ||
674 | |||
675 | bool hd24transferengine::dontopenoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix) | ||
676 | { | ||
677 | // HACK | ||
678 | trackspergroup=0; | ||
679 | |||
680 | SF_INFO sfinfoout; | ||
681 | //bool uselibsndfile=m_format_sndfile[selectedformat()]; | ||
682 | sfinfoout.format=m_format_outputformat[selectedformat()]; | ||
683 | int chcount=0; | ||
684 | if (m_format_outputchannels[selectedformat()]==0) { | ||
685 | // count channels | ||
686 | for (unsigned int handle=0;handle<channels;handle++) | ||
687 | { | ||
688 | if (job->trackselected[handle]!=0) { | ||
689 | chcount++; | ||
690 | } | ||
691 | } | ||
692 | sfinfoout.channels=chcount; | ||
693 | } else { | ||
694 | sfinfoout.channels=m_format_outputchannels[selectedformat()]; | ||
695 | } | ||
696 | if (job->usecustomrate==1) { | ||
697 | long samrate=job->stamprate; | ||
698 | sfinfoout.samplerate=samrate; | ||
699 | } else { | ||
700 | sfinfoout.samplerate=job->sourcesong()->samplerate(); | ||
701 | } | ||
702 | // chcount and lasthandle are intended to allow | ||
703 | // support for writing multichannel files. | ||
704 | int lasthandle=0; | ||
705 | int lasttrack=-1; | ||
706 | int trackcount=0; | ||
707 | int cannotopen=0; | ||
708 | chcount=0; | ||
709 | for (unsigned int handle=0;handle<channels;handle++) | ||
710 | { | ||
711 | |||
712 | islastchanofgroup[handle]=false; | ||
713 | isfirstchanofgroup[handle]=false; | ||
714 | |||
715 | if (job->trackselected[handle]==0) { | ||
716 | // channel not selected for export | ||
717 | continue; | ||
718 | } | ||
719 | trackcount++; | ||
720 | lasttrack=handle; | ||
721 | |||
722 | string* fname=generate_filename(handle,partnum,prefix); | ||
723 | if (fname==NULL) | ||
724 | { | ||
725 | // Cannot generate filename. No song set? | ||
726 | return false; // problem (not) opening files. | ||
727 | } | ||
728 | if (chcount==0) { | ||
729 | isfirstchanofgroup[handle]=true; | ||
730 | // if (uselibsndfile) | ||
731 | // { | ||
732 | // filehandle[handle]->sndfilehandle=NULL; | ||
733 | // if (soundfile->sf_open) { | ||
734 | // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile); | ||
735 | // } | ||
736 | // if (!(filehandle[handle]->handle())) | ||
737 | // { | ||
738 | // cannotopen=1; | ||
739 | // } | ||
740 | // } | ||
741 | // else | ||
742 | // { | ||
743 | // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout); | ||
744 | // } | ||
745 | lasthandle=handle; | ||
746 | } else { | ||
747 | // copy handle of previously opened file to current track | ||
748 | // filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype()); | ||
749 | // if (!(filehandle[handle]->handle())) | ||
750 | // { | ||
751 | // cannotopen=1; | ||
752 | // } | ||
753 | } | ||
754 | chcount++; | ||
755 | // if ((sfinfoout.channels)!=0) | ||
756 | // { | ||
757 | // // sfinfoout.channels=0 means full multitrack file | ||
758 | // // so only a single file will be opened. | ||
759 | // chcount=chcount%(sfinfoout.channels); | ||
760 | // if (chcount==0) { | ||
761 | // islastchanofgroup[handle]=true; | ||
762 | // if (trackspergroup==0) { | ||
763 | // trackspergroup=trackcount; | ||
764 | // } | ||
765 | // } | ||
766 | // } | ||
767 | |||
768 | delete fname; | ||
769 | } | ||
770 | |||
771 | if (lasttrack>=0) | ||
772 | { | ||
773 | if (trackspergroup==0) { | ||
774 | trackspergroup=trackcount; | ||
775 | } | ||
776 | |||
777 | islastchanofgroup[lasttrack]=true; | ||
778 | } | ||
779 | return (cannotopen==0); // return true if successful, false otherwise | ||
780 | } | ||
781 | void hd24transferengine::flushbuffer(hd24sndfile** filehandle,unsigned char** buffer,__uint32 flushbytes,unsigned int channels) | ||
782 | { | ||
783 | #if (HD24TRANSFERDEBUG==1) | ||
784 | cout << "Flushbuffer " << flushbytes << " bytes" <<endl; | ||
785 | #endif | ||
786 | for (unsigned int handle=0;handle<channels;handle++) | ||
787 | { | ||
788 | if (job->trackselected[handle]==0) continue; | ||
789 | |||
790 | writerawbuf(&(*filehandle)[handle],buffer[handle],flushbytes); | ||
791 | } | ||
792 | #if (HD24TRANSFERDEBUG==1) | ||
793 | cout << "Flushed" << endl; | ||
794 | #endif | ||
795 | } | ||
796 | |||
797 | void hd24transferengine::prepare_transfer_to_pc(__uint32 songnum, | ||
798 | __uint32 totsongs,__sint64 totbytestotransfer, | ||
799 | __sint64 totbytestransferred, | ||
800 | int wantsplit,__uint32 prefix) | ||
801 | { | ||
802 | // set properties as needed | ||
803 | cout << "prepare transfer to pc:" << endl; | ||
804 | cout << "song "<< songnum<< "/" << totsongs << ", "; | ||
805 | cout << totbytestotransfer << " total bytes to transfer" << endl; | ||
806 | cout << totbytestransferred << " transferred so far" << endl; | ||
807 | cout << "wantsplit=" << wantsplit ; | ||
808 | cout << ", prefix=" << prefix << endl; | ||
809 | this->totbytestotransfer=totbytestotransfer; | ||
810 | // this->transfer_to_pc(); | ||
811 | } | ||
812 | |||
813 | void hd24transferengine::transfer_in_progress(bool active) | ||
814 | { | ||
815 | // TODO: callback function | ||
816 | // stop_transfer->show(); | ||
817 | } | ||
818 | |||
819 | void hd24transferengine::mixleft(bool select) | ||
820 | { | ||
821 | if (select) { job->mixleft=1; } | ||
822 | } | ||
823 | |||
824 | bool hd24transferengine::mixleft() | ||
825 | { | ||
826 | if (job->mixleft==1) | ||
827 | { | ||
828 | return true; | ||
829 | } | ||
830 | return false; | ||
831 | } | ||
832 | |||
833 | void hd24transferengine::mixright(bool select) | ||
834 | { | ||
835 | if (select) { job->mixright=1; } | ||
836 | } | ||
837 | |||
838 | bool hd24transferengine::mixright() | ||
839 | { | ||
840 | if (job->mixright==1) | ||
841 | { | ||
842 | return true; | ||
843 | } | ||
844 | return false; | ||
845 | } | ||
846 | |||
847 | |||
848 | __sint64 hd24transferengine::transfer_to_pc() | ||
849 | { | ||
850 | // function returns bytes transferred for the transfer of only the current file. | ||
851 | |||
852 | __sint64 totsamcount; /* Total number of samples exported */ | ||
853 | __sint64 partsamcount; /* When splitting up the song into multiple parts, | ||
854 | number of samples exported to current part */ | ||
855 | __sint64 blockcount; /* Allows us to keep a write buffer as cache for | ||
856 | better export performance */ | ||
857 | if (job->sourcesong()==NULL) | ||
858 | { | ||
859 | return 0; | ||
860 | } | ||
861 | if (transfer_cancel==1) | ||
862 | { | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | // limit which tracks need to be actually read from HD24 disk | ||
867 | for (__uint32 i=1;i<=MAXCHANNELS;i++) | ||
868 | { | ||
869 | if (job->trackselected[i-1]==1) | ||
870 | { | ||
871 | job->sourcesong()->readenabletrack(i,true); | ||
872 | } else { | ||
873 | job->sourcesong()->readenabletrack(i,false); | ||
874 | } | ||
875 | } | ||
876 | bool mustmixdown=false; | ||
877 | if (job->mixleft==1) | ||
878 | { | ||
879 | mustmixdown=true; | ||
880 | } | ||
881 | if (job->mixright==1) | ||
882 | { | ||
883 | mustmixdown=true; | ||
884 | } | ||
885 | if (transfermixer==NULL) | ||
886 | { | ||
887 | /* as much as we'd like, there is no mixer so we can't mix. */ | ||
888 | mustmixdown=false; | ||
889 | } | ||
890 | |||
891 | #if (HD24TRANSFERDEBUG==1) | ||
892 | cout << "start export 1" << endl; | ||
893 | #endif | ||
894 | __uint32 lastremain=0xffffffff; //a | ||
895 | __uint64 songlen_sam=job->sourcesong()->songlength_in_samples()*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels()); | ||
896 | __uint32 channels=job->sourcesong()->logical_channels(); | ||
897 | __uint32 bytespersam=(job->sourcesong()->bitdepth()/8); | ||
898 | int mustdeinterlace=0; | ||
899 | if ((job->sourcesong()->samplerate())>=88200) | ||
900 | { | ||
901 | mustdeinterlace=1; | ||
902 | } | ||
903 | __uint32 oldmixersamplerate=0; | ||
904 | if (mustmixdown) | ||
905 | { | ||
906 | if (transfermixer!=NULL) { | ||
907 | oldmixersamplerate=transfermixer->samplerate(); | ||
908 | transfermixer->samplerate(job->sourcesong()->samplerate()); | ||
909 | } | ||
910 | } | ||
911 | |||
912 | #if (HD24TRANSFERDEBUG==1) | ||
913 | cout << "Channels="<<channels << endl; | ||
914 | cout << "Songlen="<<songlen_sam << endl; | ||
915 | #endif | ||
916 | double oldpct=0; | ||
917 | #if (HD24TRANSFERDEBUG==1) | ||
918 | cout << "start export 2" << endl; | ||
919 | #endif | ||
920 | |||
921 | //SNDFILE* filehandle[channels]; | ||
922 | hd24sndfile* filehandle[24]; | ||
923 | |||
924 | for (int i=0;i<MAXCHANNELS;i++) | ||
925 | { | ||
926 | filehandle[i]=new hd24sndfile(m_format_outputformat[selectedformat()],soundfile); | ||
927 | } | ||
928 | |||
929 | __uint32 partnum=0; | ||
930 | __uint64 MAXBYTES=job->sizelimit(); | ||
931 | |||
932 | /* | ||
933 | if total number of samples is likely to overflow | ||
934 | max allowable length, ask if user wants to split up | ||
935 | the files. | ||
936 | */ | ||
937 | if (job->wantsplit==1) { | ||
938 | partnum=1; // count part numbers in filename | ||
939 | } else { | ||
940 | partnum=0; // do not count part numbers in filename | ||
941 | MAXBYTES=songlen_sam*bytespersam; // allow the full song length in a single file | ||
942 | } | ||
943 | |||
944 | /* Start location 0 is absolute, all other offsets | ||
945 | are relative to the start offset. The only difference | ||
946 | is in the timecode. | ||
947 | Because of this, if startoffset>0 is given, we | ||
948 | can ignore this. */ | ||
949 | __uint64 translen; | ||
950 | __uint64 tottranslen=0; // for percentage calc in multi-song exports | ||
951 | signed int stepsize; | ||
952 | if (job->startoffset()>job->endoffset()) | ||
953 | { | ||
954 | __uint32 tempoffset=job->startoffset(); | ||
955 | job->startoffset(job->endoffset()); | ||
956 | job->endoffset(tempoffset); | ||
957 | } | ||
958 | |||
959 | translen=(job->endoffset()-job->startoffset())*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels()); | ||
960 | #if (HD24TRANSFERDEBUG==1) | ||
961 | cout << "startoffset=" << job->startoffset() << endl; | ||
962 | cout << "endoffset=" << job->endoffset() << endl; | ||
963 | #endif | ||
964 | |||
965 | if (translen==0) | ||
966 | { | ||
967 | lasterror("Start offset equals end offset- nothing to do!"); | ||
968 | } | ||
969 | stepsize=1; | ||
970 | |||
971 | bool canopen=true; | ||
972 | MixerChannelControl* mixerchannel[24]; | ||
973 | for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++) | ||
974 | { | ||
975 | mixerchannel[tracknum]=NULL; | ||
976 | } | ||
977 | |||
978 | if (mustmixdown) | ||
979 | { | ||
980 | for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++) | ||
981 | { | ||
982 | mixerchannel[tracknum]=transfermixer->parentui()->mixerchannel[tracknum]->control; | ||
983 | } | ||
984 | // HACK | ||
985 | canopen=dontopenoutputfiles( | ||
986 | (hd24sndfile**)&filehandle[0], | ||
987 | channels, | ||
988 | partnum, | ||
989 | prefix); // partnum is for splitting large files | ||
990 | } else { | ||
991 | canopen=openoutputfiles( | ||
992 | (hd24sndfile**)&filehandle[0], | ||
993 | channels, | ||
994 | partnum, | ||
995 | prefix); // partnum is for splitting large files | ||
996 | } | ||
997 | |||
998 | if (!canopen) | ||
999 | { | ||
1000 | #if (HD24TRANSFERDEBUG==1) | ||
1001 | cout << "error opening output files" << endl; | ||
1002 | #endif | ||
1003 | transfer_cancel=1; | ||
1004 | return 0; | ||
1005 | } else { | ||
1006 | transfer_cancel=0; | ||
1007 | } | ||
1008 | |||
1009 | this->transfer_in_progress(true); | ||
1010 | time (&starttime); | ||
1011 | |||
1012 | partsamcount=0; totsamcount=0; | ||
1013 | int trackwithingroup=0; | ||
1014 | #if (HD24TRANSFERDEBUG==1) | ||
1015 | cout << "songlen in samples=" << songlen_sam << endl; | ||
1016 | #endif | ||
1017 | blockcount=0; // for buffered writing. | ||
1018 | hd24fs* currenthd24=job->sourcefs(); | ||
1019 | if (currenthd24==NULL) | ||
1020 | { | ||
1021 | cout << "Critical error- current FS not defined." << endl; | ||
1022 | } | ||
1023 | int blocksize=currenthd24->getbytesperaudioblock(); | ||
1024 | // to hold normally read audio data: | ||
1025 | unsigned char* audiodata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1); | ||
1026 | |||
1027 | // for high-samplerate block deinterlacing: | ||
1028 | unsigned char* deinterlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1); | ||
1029 | |||
1030 | // for interlacing multi-track data: | ||
1031 | unsigned char* interlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1); | ||
1032 | |||
1033 | |||
1034 | __uint32 samplesperblock=(blocksize/channels)/bytespersam; | ||
1035 | float* outputBuffer=NULL; | ||
1036 | SF_INFO infoblock; | ||
1037 | hd24sndfile* mixdownfile=NULL; | ||
1038 | if (mustmixdown) | ||
1039 | { | ||
1040 | outputBuffer=(float*)malloc(2*samplesperblock*sizeof(float)); // 2 because it is stereo | ||
1041 | mixdownfile=new hd24sndfile(SF_FORMAT_WAV|SF_FORMAT_PCM_32 | ||
1042 | |SF_FORMAT_FLOAT,soundfile); | ||
1043 | infoblock.channels=2; | ||
1044 | infoblock.samplerate=job->sourcesong()->samplerate(); | ||
1045 | infoblock.format=SF_FORMAT_WAV|SF_FORMAT_PCM_32|SF_FORMAT_FLOAT; | ||
1046 | |||
1047 | int mixdownfilenum=0; | ||
1048 | int fileopensuccess=0; | ||
1049 | do { | ||
1050 | string* mixdownfilename=new string(""); | ||
1051 | *mixdownfilename+=*job->m_projectdir; | ||
1052 | string* currsongname=job->sourcesong()->songname(); | ||
1053 | *mixdownfilename+=*currsongname; | ||
1054 | delete currsongname; | ||
1055 | *mixdownfilename+="_mixdown"; | ||
1056 | if (mixdownfilenum>0) | ||
1057 | { | ||
1058 | *mixdownfilename+="_"; | ||
1059 | string* mixnumstr=Convert::int2str(mixdownfilenum); | ||
1060 | *mixdownfilename+=*mixnumstr; | ||
1061 | delete mixnumstr; | ||
1062 | } | ||
1063 | *mixdownfilename+=".wav"; | ||
1064 | if (!hd24utils::fileExists(mixdownfilename->c_str())) | ||
1065 | { | ||
1066 | mixdownfile->open(mixdownfilename->c_str(),SFM_WRITE,&infoblock,soundfile); | ||
1067 | fileopensuccess=1; | ||
1068 | } | ||
1069 | mixdownfilenum++; | ||
1070 | delete mixdownfilename; | ||
1071 | } while (fileopensuccess==0); | ||
1072 | } | ||
1073 | |||
1074 | |||
1075 | __uint32 samplesinfirstblock=samplesperblock; | ||
1076 | if (job->startoffset()!=0) { | ||
1077 | if (job->startoffset()>=samplesperblock) { | ||
1078 | samplesinfirstblock=samplesperblock-(job->startoffset()%samplesperblock); | ||
1079 | } else { | ||
1080 | samplesinfirstblock=samplesperblock-(job->startoffset()); | ||
1081 | } | ||
1082 | } | ||
1083 | #if (HD24TRANSFERDEBUG==1) | ||
1084 | cout << "go to startoffset " << job->startoffset() << endl; | ||
1085 | #endif | ||
1086 | job->sourcesong()->golocatepos(job->startoffset()); | ||
1087 | #if (HD24TRANSFERDEBUG==1) | ||
1088 | cout << "got to startoffset " << job->startoffset() << endl; | ||
1089 | cout << "translen= " << translen << endl; | ||
1090 | #endif | ||
1091 | __uint32 subblocksize=samplesperblock*bytespersam; | ||
1092 | __uint32 samplesinblock=samplesinfirstblock; | ||
1093 | if (translen<samplesperblock) | ||
1094 | { | ||
1095 | samplesinfirstblock=translen; | ||
1096 | } | ||
1097 | |||
1098 | __sint64 difseconds=0; | ||
1099 | __sint64 olddifseconds=0; | ||
1100 | __uint64 bytestransferred=0; | ||
1101 | |||
1102 | for (__uint32 samplenum=0; | ||
1103 | samplenum<translen; | ||
1104 | samplenum+=samplesinblock) | ||
1105 | { | ||
1106 | if (transfer_cancel==1) | ||
1107 | { | ||
1108 | break; | ||
1109 | } | ||
1110 | __uint32 subblockbytes=subblocksize; | ||
1111 | if (translen==samplesinfirstblock) | ||
1112 | { | ||
1113 | #if (HD24TRANSFERDEBUG==1) | ||
1114 | cout << "translen==samplesinfirstblock" << endl; | ||
1115 | subblockbytes=translen*bytespersam; | ||
1116 | samplesinblock=samplesinfirstblock; | ||
1117 | #endif | ||
1118 | } else { | ||
1119 | if (samplenum==0) { | ||
1120 | samplesinblock=samplesinfirstblock; | ||
1121 | } | ||
1122 | else | ||
1123 | { | ||
1124 | samplesinblock=samplesperblock; | ||
1125 | } | ||
1126 | |||
1127 | if (samplenum+samplesinblock>=translen) | ||
1128 | { | ||
1129 | subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam; | ||
1130 | } else { | ||
1131 | if (samplesinblock!=samplesperblock) | ||
1132 | { | ||
1133 | subblockbytes=samplesinblock*bytespersam; | ||
1134 | } | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | #if (HD24TRANSFERDEBUG==1) | ||
1139 | cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl; | ||
1140 | #endif | ||
1141 | |||
1142 | int skipsams=job->sourcesong()->getmtrackaudiodata(samplenum+job->startoffset(),samplesinblock,&audiodata[0],hd24song::READMODE_COPY); | ||
1143 | unsigned char* whattowrite=&audiodata[0]; | ||
1144 | if (mustdeinterlace==1) | ||
1145 | { | ||
1146 | job->sourcesong()->deinterlaceblock(&audiodata[0],&deinterlacedata[0]); | ||
1147 | whattowrite=&deinterlacedata[0]; | ||
1148 | } | ||
1149 | |||
1150 | #if (HD24TRANSFERDEBUG==1) | ||
1151 | cout << "check for split" << endl; | ||
1152 | #endif | ||
1153 | if (job->wantsplit==1) | ||
1154 | { | ||
1155 | __uint64 filesize=partsamcount; | ||
1156 | filesize+=samplesinblock; | ||
1157 | filesize*=bytespersam; | ||
1158 | if (filesize>MAXBYTES) /// total filesize reached for current part | ||
1159 | { | ||
1160 | closeoutputfiles((hd24sndfile**)&filehandle[0],channels); | ||
1161 | partnum++; | ||
1162 | openoutputfiles((hd24sndfile**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files | ||
1163 | partsamcount=0; | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | // check if we need to save a mixdown | ||
1168 | if (mustmixdown) | ||
1169 | { | ||
1170 | #if (HD24TRANSFERDEBUG==1) | ||
1171 | cout << "Mixing " << endl; | ||
1172 | #endif | ||
1173 | |||
1174 | for (__uint32 tracknum=0;tracknum<channels;tracknum++) | ||
1175 | { | ||
1176 | unsigned char* currsam=&whattowrite[tracknum*subblocksize | ||
1177 | +((mustdeinterlace+1)*skipsams*bytespersam)]; | ||
1178 | for (__uint32 samnum=0;samnum<subblockbytes;samnum+=3) | ||
1179 | { | ||
1180 | float subsamval=currsam[samnum+0] | ||
1181 | +(currsam[samnum+1]<<8) | ||
1182 | +(currsam[samnum+2]<<16); | ||
1183 | |||
1184 | if (subsamval>=(1<<23)) { | ||
1185 | subsamval-=(1<<24); | ||
1186 | } | ||
1187 | subsamval=(subsamval/(double)0x800000); | ||
1188 | mixerchannel[tracknum]->sample(samnum/3,subsamval); | ||
1189 | } | ||
1190 | } | ||
1191 | transfermixer->mix(subblockbytes/3); | ||
1192 | |||
1193 | if (outputBuffer!=NULL) | ||
1194 | { | ||
1195 | // if stereo output, interlace (TODO: check if this is what we want) | ||
1196 | for (__uint32 i=0;i<(subblockbytes/3);i++) | ||
1197 | { | ||
1198 | ((float*)outputBuffer)[i*2] = transfermixer->masterout(0,i); // left | ||
1199 | ((float*)outputBuffer)[i*2+1] = transfermixer->masterout(1,i); // right | ||
1200 | } | ||
1201 | mixdownfile->write_float(outputBuffer,(subblockbytes/3)*infoblock.channels); | ||
1202 | } | ||
1203 | } | ||
1204 | // when mixing down, let's not export raw files as well. | ||
1205 | |||
1206 | for (__uint32 tracknum=0;tracknum<channels;tracknum++) | ||
1207 | { | ||
1208 | if (job->trackselected[tracknum]==0) | ||
1209 | { | ||
1210 | // track not selected for export | ||
1211 | #if (HD24TRANSFERDEBUG==1) | ||
1212 | cout << "Track " << tracknum+1 << " not selected for export " << endl; | ||
1213 | #endif | ||
1214 | continue; | ||
1215 | } | ||
1216 | |||
1217 | if (transfer_cancel==1) | ||
1218 | { | ||
1219 | #if (HD24TRANSFERDEBUG==1) | ||
1220 | cout << "Transfer cancelled by user. " << endl; | ||
1221 | #endif | ||
1222 | break; | ||
1223 | } | ||
1224 | |||
1225 | // Mono files or multiple tracks? | ||
1226 | if ( | ||
1227 | (isfirstchanofgroup[tracknum]) | ||
1228 | &&(islastchanofgroup[tracknum]) | ||
1229 | ) { | ||
1230 | // file is mono | ||
1231 | if (!mustmixdown) { | ||
1232 | writerawbuf(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes); | ||
1233 | } | ||
1234 | bytestransferred+=subblockbytes; | ||
1235 | } else { | ||
1236 | if (isfirstchanofgroup[tracknum]) { | ||
1237 | // first channel of group, clear interlace buffer | ||
1238 | trackwithingroup=0; | ||
1239 | #if (HD24TRANSFERDEBUG==1) | ||
1240 | cout << "first track " << samplenum << endl; | ||
1241 | #endif | ||
1242 | } else { | ||
1243 | trackwithingroup++; | ||
1244 | #if (HD24TRANSFERDEBUG==1) | ||
1245 | cout << "nonfirst track " << samplenum << endl; | ||
1246 | #endif | ||
1247 | } | ||
1248 | // interlace channel onto multi channel file buffer | ||
1249 | if (!mustmixdown) { | ||
1250 | hd24utils::interlacetobuffer(&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],&interlacedata[0],subblockbytes,bytespersam,trackwithingroup,trackspergroup); | ||
1251 | } | ||
1252 | |||
1253 | if (islastchanofgroup[tracknum]) { | ||
1254 | // last channel of group, write interlace buffer to file | ||
1255 | #if (HD24TRANSFERDEBUG==1) | ||
1256 | cout << "write track " << samplenum << endl; | ||
1257 | #endif | ||
1258 | //soundfile->sf_write_raw(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup); | ||
1259 | if (!mustmixdown) { | ||
1260 | writerawbuf(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup); | ||
1261 | } | ||
1262 | bytestransferred+=subblockbytes*trackspergroup; | ||
1263 | } | ||
1264 | } | ||
1265 | } | ||
1266 | partsamcount+=(subblockbytes/bytespersam); | ||
1267 | // totsamcount+=subblockbytes; | ||
1268 | |||
1269 | __uint32 pct; // to use for display percentage | ||
1270 | double dblpct; // to use for ETA calculation | ||
1271 | #if (HD24TRANSFERDEBUG==1) | ||
1272 | cout << "about to calc pct" << endl; | ||
1273 | cout << "totbytestransferred=" << totbytestransferred; | ||
1274 | cout << ", currbytestransferred=" << bytestransferred; | ||
1275 | cout << ", totbytestotransfer=" << totbytestotransfer; | ||
1276 | cout << endl; | ||
1277 | #endif | ||
1278 | |||
1279 | /* following two calculations give the same mathematical result | ||
1280 | but help keep the required word length narrow for large numbers | ||
1281 | and reduce floating point rounding errors for small numbers. | ||
1282 | */ | ||
1283 | if (tottranslen<100000) | ||
1284 | { | ||
1285 | dblpct=( | ||
1286 | ( | ||
1287 | ( | ||
1288 | (double)totbytestransferred | ||
1289 | +(double)bytestransferred | ||
1290 | ) | ||
1291 | *(double)100 | ||
1292 | ) | ||
1293 | / | ||
1294 | (double)totbytestotransfer | ||
1295 | ); | ||
1296 | } | ||
1297 | else | ||
1298 | { | ||
1299 | dblpct=( | ||
1300 | ( | ||
1301 | (double)totbytestransferred | ||
1302 | +(double)bytestransferred | ||
1303 | ) | ||
1304 | / | ||
1305 | (double) | ||
1306 | ( | ||
1307 | (double)totbytestotransfer | ||
1308 | / | ||
1309 | (double)100 | ||
1310 | ) | ||
1311 | ); | ||
1312 | } | ||
1313 | pct=(__uint32)(dblpct); | ||
1314 | |||
1315 | #if (HD24TRANSFERDEBUG==1) | ||
1316 | cout << "about to calc pct2" << endl; | ||
1317 | #endif | ||
1318 | |||
1319 | #if (HD24TRANSFERDEBUG==1) | ||
1320 | cout << "computed pct " << samplenum << endl; | ||
1321 | #endif | ||
1322 | time (&endtime); | ||
1323 | olddifseconds=difseconds; | ||
1324 | difseconds=(long long int)difftime(endtime,starttime); | ||
1325 | |||
1326 | if (((dblpct-oldpct)>=1) || ((difseconds-olddifseconds)>=1)) | ||
1327 | { | ||
1328 | /* update on percentage change, and also every | ||
1329 | so many samples (to allow frequent enough | ||
1330 | screen updates with large audio files) */ | ||
1331 | oldpct=dblpct; | ||
1332 | |||
1333 | string pctmsg="Transferring audio to PC... "; | ||
1334 | if (totsongs>1) | ||
1335 | { | ||
1336 | pctmsg+="Song "; | ||
1337 | string* cursongnum=Convert::int2str(songnum); | ||
1338 | pctmsg+=*cursongnum+"/"; | ||
1339 | delete cursongnum; | ||
1340 | string* totsongnum=Convert::int2str(totsongs); | ||
1341 | pctmsg+=*totsongnum+", "; | ||
1342 | delete totsongnum; | ||
1343 | } | ||
1344 | string* strpct=Convert::int2str(pct); | ||
1345 | pctmsg+=*strpct+"%"; | ||
1346 | |||
1347 | if (pct>0) | ||
1348 | { | ||
1349 | __uint32 estimated_seconds=(__uint32)((difseconds*100)/dblpct); | ||
1350 | __uint32 remaining_seconds=estimated_seconds-difseconds; | ||
1351 | |||
1352 | lastremain=remaining_seconds; | ||
1353 | |||
1354 | __uint32 seconds=(lastremain%60); | ||
1355 | __uint32 minutes=(lastremain-seconds)/60; | ||
1356 | __uint32 hours=0; | ||
1357 | |||
1358 | pctmsg+=" Time remaining: "; | ||
1359 | |||
1360 | if (minutes>59) { | ||
1361 | hours=(minutes/60); | ||
1362 | minutes=(minutes%60); | ||
1363 | string* strhours=Convert::int2str(hours,2,"0"); | ||
1364 | pctmsg+=*strhours; | ||
1365 | pctmsg+=":"; | ||
1366 | delete(strhours); | ||
1367 | } | ||
1368 | |||
1369 | string* minsec=Convert::int2str(minutes,2,"0"); | ||
1370 | |||
1371 | *minsec+=":"; | ||
1372 | |||
1373 | string* strsecs=Convert::int2str(seconds,2,"0"); | ||
1374 | *minsec+=*strsecs; | ||
1375 | delete(strsecs); | ||
1376 | |||
1377 | pctmsg+=*minsec; | ||
1378 | delete(minsec); | ||
1379 | } | ||
1380 | |||
1381 | delete (strpct); | ||
1382 | setstatus(ui,&pctmsg,dblpct); | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | closeoutputfiles((hd24sndfile**)&filehandle[0],channels); | ||
1387 | for (int i=0;i<MAXCHANNELS;i++) { | ||
1388 | if (filehandle[i]!=NULL) | ||
1389 | { | ||
1390 | delete filehandle[i]; | ||
1391 | } | ||
1392 | } | ||
1393 | // from now on we'll read all tracks again | ||
1394 | for (__uint32 i=1;i<=MAXCHANNELS;i++) | ||
1395 | { | ||
1396 | if (job->trackselected[i-1]==1) | ||
1397 | { | ||
1398 | job->sourcesong()->readenabletrack(i,true); | ||
1399 | } | ||
1400 | } | ||
1401 | if (audiodata!=NULL) | ||
1402 | { | ||
1403 | free (audiodata); | ||
1404 | } | ||
1405 | if (deinterlacedata!=NULL) | ||
1406 | { | ||
1407 | free (deinterlacedata); | ||
1408 | } | ||
1409 | if (interlacedata!=NULL) | ||
1410 | { | ||
1411 | free (interlacedata); | ||
1412 | } | ||
1413 | if (outputBuffer!=NULL) | ||
1414 | { | ||
1415 | free (outputBuffer); | ||
1416 | } | ||
1417 | if (mixdownfile!=NULL) | ||
1418 | { | ||
1419 | mixdownfile->close(); | ||
1420 | } | ||
1421 | if (transfermixer!=NULL) { | ||
1422 | transfermixer->samplerate(oldmixersamplerate); | ||
1423 | } | ||
1424 | |||
1425 | return bytestransferred; | ||
1426 | } | ||
1427 | |||
1428 | void hd24transferengine::selectedformat(int i) | ||
1429 | { | ||
1430 | if (i>=formatcount) return; | ||
1431 | job->selectedformat(i); | ||
1432 | } | ||
1433 | void hd24transferjob::selectedformat(int i) | ||
1434 | { | ||
1435 | m_selectedformat=i; | ||
1436 | } | ||
1437 | |||
1438 | int hd24transferengine::selectedformat() | ||
1439 | { | ||
1440 | return job->selectedformat(); | ||
1441 | } | ||
1442 | int hd24transferjob::selectedformat() | ||
1443 | { | ||
1444 | return m_selectedformat; | ||
1445 | } | ||
1446 | |||
1447 | void hd24transferengine::mixer(MixerControl* m_mixer) | ||
1448 | { | ||
1449 | this->transfermixer=m_mixer; | ||
1450 | } | ||
1451 | |||
1452 | MixerControl* hd24transferengine::mixer() | ||
1453 | { | ||
1454 | return this->transfermixer; | ||
1455 | } | ||
1456 | |||
1457 | string* hd24transferengine::generate_filename(int tracknum,int partnum,int prefix) | ||
1458 | { | ||
1459 | #if (HD24TRANSFERDEBUG==1) | ||
1460 | cout << "hd24transferengine::generate_filename(track=" << tracknum << ",part="<<partnum<<",prefix="<<prefix<<endl; | ||
1461 | cout << "Selected format="<<selectedformat() << endl; | ||
1462 | #endif | ||
1463 | #if (HD24TRANSFERDEBUG==1) | ||
1464 | cout << "Job="<<job<<endl; | ||
1465 | #endif | ||
1466 | #if (HD24TRANSFERDEBUG==1) | ||
1467 | cout << "Projdir="<<job->m_projectdir<<endl; | ||
1468 | #endif | ||
1469 | if (job->m_projectdir==NULL) | ||
1470 | { | ||
1471 | cout << "No project dir set!" << endl; | ||
1472 | return NULL; | ||
1473 | } | ||
1474 | const char* pdir=job->m_projectdir->c_str(); //projectdir(); | ||
1475 | #if (HD24TRANSFERDEBUG==1) | ||
1476 | cout << "Projdir (const char*)="<<pdir << endl; | ||
1477 | #endif | ||
1478 | |||
1479 | if (pdir==NULL) | ||
1480 | { | ||
1481 | cout << "No project dir set!" << endl; | ||
1482 | return NULL; | ||
1483 | } | ||
1484 | string* dirname=new string(pdir); | ||
1485 | if (dirname->substr(dirname->length()-1,1)!="/") { | ||
1486 | *dirname+="/"; | ||
1487 | } | ||
1488 | #if (HD24TRANSFERDEBUG==1) | ||
1489 | cout << "filename so far is just dir with slash=" << *dirname << endl; | ||
1490 | #endif | ||
1491 | string* fname=new string(dirname->c_str()); | ||
1492 | delete dirname; | ||
1493 | if (prefix!=0) | ||
1494 | { | ||
1495 | string* strsongnum=Convert::int2str(prefix,2,"0"); | ||
1496 | *fname+="Song"; | ||
1497 | *fname+=*strsongnum; | ||
1498 | *fname+="-"; | ||
1499 | delete (strsongnum); | ||
1500 | } | ||
1501 | #if (HD24TRANSFERDEBUG==1) | ||
1502 | cout << "filename so far is " << *fname << endl; | ||
1503 | cout << "About to add songname" << endl; | ||
1504 | #endif | ||
1505 | if (job->sourcesong()==NULL) | ||
1506 | { | ||
1507 | #if (HD24TRANSFERDEBUG==1) | ||
1508 | cout << "No song set!" << endl; | ||
1509 | #endif | ||
1510 | return NULL; | ||
1511 | } | ||
1512 | |||
1513 | string* strsongname=job->sourcesong()->songname(); | ||
1514 | *fname+=*strsongname; | ||
1515 | delete (strsongname); | ||
1516 | |||
1517 | #if (HD24TRANSFERDEBUG==1) | ||
1518 | cout << "filename so far is " << *fname << endl; | ||
1519 | cout << "About to add track constant" << endl; | ||
1520 | #endif | ||
1521 | *fname+="-Track"; | ||
1522 | #if (HD24TRANSFERDEBUG==1) | ||
1523 | cout << "filename so far is " << *fname << endl; | ||
1524 | cout << "About to add tracknum" << (tracknum+2) << endl; | ||
1525 | #endif | ||
1526 | string* strtracknum=Convert::int2str(tracknum+1,2,"0"); | ||
1527 | *fname+=*strtracknum; | ||
1528 | delete (strtracknum); | ||
1529 | if (partnum>0) { | ||
1530 | /* partnum 0 implies no splitting and thus no partnum | ||
1531 | added to the filename. In other words, we either use | ||
1532 | partnum 0 (invisible in filename), or partnum 1-n. */ | ||
1533 | *fname+="_part"; | ||
1534 | *fname+=*Convert::int2str(partnum); | ||
1535 | } | ||
1536 | string* extension=new string((*m_format_outputextension)[selectedformat()]); | ||
1537 | *fname+=*extension; | ||
1538 | delete extension; | ||
1539 | #if (HD24TRANSFERDEBUG==1) | ||
1540 | cout << "Generated filename="<<fname<<endl; | ||
1541 | #endif | ||
1542 | return fname; | ||
1543 | } | ||
1544 | |||
1545 | void hd24transferjob::sizelimit(__sint64 p_sizelimit) | ||
1546 | { | ||
1547 | this->llsizelimit=p_sizelimit; | ||
1548 | } | ||
1549 | |||
1550 | __sint64 hd24transferjob::sizelimit() | ||
1551 | { | ||
1552 | return this->llsizelimit; | ||
1553 | } | ||
1554 | |||
1555 | void hd24transferengine::sizelimit(__sint64 p_sizelimit) | ||
1556 | { | ||
1557 | job->sizelimit(p_sizelimit); | ||
1558 | } | ||
1559 | |||
1560 | __sint64 hd24transferengine::sizelimit() | ||
1561 | { | ||
1562 | return job->sizelimit(); | ||
1563 | } | ||
1564 | |||
1565 | bool hd24transferengine::anyfilesexist(hd24song* thesong) | ||
1566 | { | ||
1567 | bool anyexist=false; | ||
1568 | struct stat fi; | ||
1569 | __uint32 channels=thesong->logical_channels(); | ||
1570 | for (unsigned int q=0; q<100; q++) | ||
1571 | { | ||
1572 | for (unsigned int handle=0;handle<channels;handle++) | ||
1573 | { | ||
1574 | if (job->trackselected[handle]==0) | ||
1575 | { | ||
1576 | // channel not selected for export | ||
1577 | continue; | ||
1578 | } | ||
1579 | string* fname=this->generate_filename(handle,0,q); | ||
1580 | if (fname==NULL) | ||
1581 | { | ||
1582 | // cannot generate filename (no song set?) | ||
1583 | break; | ||
1584 | } | ||
1585 | #if (HD24TRANSFERDEBUG==1) | ||
1586 | cout << "check if file exists:" << *fname << endl; | ||
1587 | #endif | ||
1588 | if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) | ||
1589 | { | ||
1590 | anyexist=true; | ||
1591 | #if (HD24TRANSFERDEBUG==1) | ||
1592 | cout << "yes, exists" << *fname << endl; | ||
1593 | #endif | ||
1594 | delete fname; | ||
1595 | break; | ||
1596 | } | ||
1597 | |||
1598 | fname=this->generate_filename(handle,1,q); | ||
1599 | if (fname==NULL) | ||
1600 | { | ||
1601 | // cannot generate filename (no song set?) | ||
1602 | break; | ||
1603 | } | ||
1604 | #if (HD24TRANSFERDEBUG==1) | ||
1605 | cout << "check if file exists:" << *fname << endl; | ||
1606 | #endif | ||
1607 | if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) | ||
1608 | { | ||
1609 | anyexist=true; | ||
1610 | #if (HD24TRANSFERDEBUG==1) | ||
1611 | cout << "yes, exists" << *fname << endl; | ||
1612 | #endif | ||
1613 | delete fname; | ||
1614 | break; | ||
1615 | } | ||
1616 | #if (HD24TRANSFERDEBUG==1) | ||
1617 | cout << "no, doesnt exist" << endl; | ||
1618 | #endif | ||
1619 | |||
1620 | delete fname; | ||
1621 | } | ||
1622 | if (anyexist==true) break; | ||
1623 | } | ||
1624 | return anyexist; | ||
1625 | } | ||
1626 | |||
1627 | void hd24transferengine::setstatus(void* ui,string* message,double percentage) | ||
1628 | { | ||
1629 | #if (HD24TRANSFERDEBUG==1) | ||
1630 | printf(message->c_str(),percentage); | ||
1631 | cout << endl; | ||
1632 | #endif | ||
1633 | if (setstatusfunction!=NULL) | ||
1634 | { | ||
1635 | setstatusfunction(ui,message->c_str(),percentage); | ||
1636 | } | ||
1637 | return; | ||
1638 | } | ||
1639 | |||
1640 | void hd24transferengine::set_ui(void* p_ui) | ||
1641 | { | ||
1642 | this->ui=p_ui; | ||
1643 | } | ||
1644 | |||
1645 | void hd24transferengine::sourcesong(hd24song* song) | ||
1646 | { | ||
1647 | #if (HD24TRANSFERDEBUG==1) | ||
1648 | cout << "hd24transferengine::sourcesong(" << song << ")" << endl; | ||
1649 | #endif | ||
1650 | if (this->job==NULL) | ||
1651 | { | ||
1652 | return; | ||
1653 | } | ||
1654 | this->job->sourcesong(song); | ||
1655 | } | ||
1656 | |||
1657 | hd24song* hd24transferengine::sourcesong() | ||
1658 | { | ||
1659 | #if (HD24TRANSFERDEBUG==1) | ||
1660 | cout << "hd24transferengine::sourcesong()=" | ||
1661 | << this->job->sourcesong()<< endl; | ||
1662 | #endif | ||
1663 | if (this->job==NULL) | ||
1664 | { | ||
1665 | return NULL; | ||
1666 | } | ||
1667 | return this->job->sourcesong(); | ||
1668 | } | ||
1669 | |||
1670 | void hd24transferengine::startoffset(__uint32 newoff) | ||
1671 | { | ||
1672 | job->startoffset(newoff); | ||
1673 | } | ||
1674 | |||
1675 | void hd24transferengine::endoffset(__uint32 newoff) | ||
1676 | { | ||
1677 | job->endoffset(newoff); | ||
1678 | } | ||
1679 | |||
1680 | __uint32 hd24transferengine::startoffset() | ||
1681 | { | ||
1682 | return job->startoffset(); | ||
1683 | } | ||
1684 | |||
1685 | __uint32 hd24transferengine::endoffset() | ||
1686 | { | ||
1687 | return job->endoffset(); | ||
1688 | } | ||
1689 | |||
1690 | void hd24transferengine::targetsong(hd24song* song) | ||
1691 | { | ||
1692 | if (job==NULL) | ||
1693 | { | ||
1694 | return; | ||
1695 | } | ||
1696 | job->targetsong(song); | ||
1697 | } | ||
1698 | |||
1699 | hd24song* hd24transferengine::targetsong() | ||
1700 | { | ||
1701 | if (job==NULL) | ||
1702 | { | ||
1703 | return NULL; | ||
1704 | } | ||
1705 | return job->targetsong(); | ||
1706 | } | ||
1707 | |||
1708 | __sint64 hd24transferengine::transfer_to_hd24() | ||
1709 | { | ||
1710 | if (job->targetsong()==NULL) | ||
1711 | { | ||
1712 | lasterror("No target song selected, transfer aborted."); | ||
1713 | return 0; | ||
1714 | } | ||
1715 | if (soundfile==NULL) | ||
1716 | { | ||
1717 | lasterror("soundfile library not defined, transfer aborted"); | ||
1718 | return 0; | ||
1719 | } | ||
1720 | job->targetsong()->golocatepos(0); | ||
1721 | job->targetsong()->startrecord(hd24song::WRITEMODE_COPY); | ||
1722 | |||
1723 | //mustdisplaytimer=false; | ||
1724 | __sint64 bytestransferred=0; | ||
1725 | |||
1726 | for (unsigned int currchan=0;currchan<MAXCHANNELS;currchan++) { | ||
1727 | job->filehandle[currchan]=NULL; | ||
1728 | audiobuf[currchan]=NULL; | ||
1729 | } | ||
1730 | SF_INFO sfinfoin[24]; | ||
1731 | bool canopen=this->openinputfiles((SNDFILE**)&(job->filehandle[0]),(SF_INFO*)&sfinfoin[0],job->targetsong()->logical_channels()); | ||
1732 | if (!canopen) | ||
1733 | { | ||
1734 | return 0; | ||
1735 | } | ||
1736 | // Find file with largest number of samples; | ||
1737 | // if song is shorter than that, lengthen song to fit it. | ||
1738 | __sint64 translen=job->targetsong()->songlength_in_samples(); | ||
1739 | __uint32 maxlen=(__uint32)translen; | ||
1740 | bool mustlengthensong=false; | ||
1741 | for (int i=0;i<MAXCHANNELS;i++) { | ||
1742 | if (job->filehandle[i]==NULL) continue; | ||
1743 | if (((__sint64)sfinfoin[i].frames) > (__sint64)maxlen) { | ||
1744 | maxlen=sfinfoin[i].frames; | ||
1745 | mustlengthensong=true; | ||
1746 | } | ||
1747 | } | ||
1748 | if (mustlengthensong) { | ||
1749 | string* lengthening=new string("Transferring audio to HD24... "); | ||
1750 | setstatus(ui,lengthening,0); | ||
1751 | delete lengthening; | ||
1752 | #if (HD24TRANSFERDEBUG==1) | ||
1753 | cout << "about to start lengthening song to maxlen=" << maxlen << endl; | ||
1754 | #endif | ||
1755 | bool clearnew=false; // do not silence newly allocated part | ||
1756 | // (it is done automatically during transfer) | ||
1757 | translen=job->targetsong()->songlength_in_samples(maxlen,clearnew); | ||
1758 | #if (HD24TRANSFERDEBUG==1) | ||
1759 | cout << "verifying actual song length " << endl; | ||
1760 | cout << "new len=" << translen << endl; | ||
1761 | #endif | ||
1762 | if (translen!=maxlen) | ||
1763 | { | ||
1764 | #if (HD24TRANSFERDEBUG==1) | ||
1765 | cout << "new len<> maxlen so not enough space." << endl; | ||
1766 | #endif | ||
1767 | this->lasterror("Not enough space on HD24 drive."); | ||
1768 | return 0; | ||
1769 | } | ||
1770 | job->targetsong()->save(); | ||
1771 | // ui_refresh("tohd24"); | ||
1772 | #if (HD24TRANSFERDEBUG==1) | ||
1773 | cout << "translen is now " << translen << endl; | ||
1774 | #endif | ||
1775 | |||
1776 | } | ||
1777 | hd24fs* currenthd24=job->targetfs(); | ||
1778 | int blocksize=currenthd24->getbytesperaudioblock(); | ||
1779 | // to hold normally read audio data: | ||
1780 | unsigned char* audiodata=NULL; | ||
1781 | transfer_cancel=0; | ||
1782 | // ui->stop_transfer->show(); | ||
1783 | |||
1784 | audiodata=(unsigned char*)memutils::mymalloc("button_transfertohd24",blocksize,1); | ||
1785 | __uint32 channels=job->targetsong()->logical_channels(); | ||
1786 | __uint32 bytespersam=(job->targetsong()->bitdepth()/8); | ||
1787 | __uint32 samplesperblock=(blocksize/channels)/bytespersam; | ||
1788 | job->smptegen=new SMPTEgenerator(job->targetsong()->samplerate()); | ||
1789 | |||
1790 | for (unsigned int fh=0;fh<MAXCHANNELS;fh++) { | ||
1791 | int action=job->trackaction(fh+1); | ||
1792 | if ((job->filehandle[fh]!=NULL)||(action<=1 /* erase, SMPTE stripe */)) { | ||
1793 | __uint32 chans=((action==0)||(action==1))?(1):(sfinfoin[fh].channels); | ||
1794 | __uint32 bytestoalloc=chans*samplesperblock*sizeof(int); | ||
1795 | audiobuf[fh]=(int*)memutils::mymalloc( | ||
1796 | "button_transfertohd24 audiobuf",bytestoalloc,1 | ||
1797 | ); | ||
1798 | |||
1799 | if (action == 0) { | ||
1800 | // clear erase buffer once | ||
1801 | int* buf=audiobuf[fh]; | ||
1802 | for (__uint32 samnum=0;samnum<samplesperblock;samnum++) { | ||
1803 | buf[samnum]=0; | ||
1804 | } | ||
1805 | } | ||
1806 | if (action == 1) { | ||
1807 | // clear SMPTE buffer once (mostly for debugging purposes) | ||
1808 | int* buf=audiobuf[fh]; | ||
1809 | for (__uint32 samnum=0;samnum<samplesperblock;samnum++) { | ||
1810 | buf[samnum]=1; | ||
1811 | } | ||
1812 | } | ||
1813 | // if action==1, we need to repopulate the buffer while striping | ||
1814 | } else { | ||
1815 | audiobuf[fh]=NULL; | ||
1816 | } | ||
1817 | } | ||
1818 | |||
1819 | // number of samples in current block- equal to block samples for full song | ||
1820 | // transfer | ||
1821 | __uint32 subblocksize=samplesperblock*bytespersam; | ||
1822 | |||
1823 | int mustinterlace=0; | ||
1824 | if ((job->targetsong()->samplerate())>=88200) | ||
1825 | { | ||
1826 | mustinterlace=1; | ||
1827 | } | ||
1828 | #if (HD24TRANSFERDEBUG==1) | ||
1829 | cout << "Channels="<<channels << endl; | ||
1830 | #endif | ||
1831 | __uint32 startoffset=0; | ||
1832 | //__uint32 endoffset=currsong->songlength_in_samples(); | ||
1833 | __uint32 samplesinfirstblock=samplesperblock; | ||
1834 | |||
1835 | job->targetsong()->getlocatepos(25); // 25= virtual endpoint of song | ||
1836 | // calc number of samples to transfer. | ||
1837 | // for high samplerate songs, this is twice the songlength. | ||
1838 | // (for partial transfers, which are not supported at this time, the | ||
1839 | // number of samples is based on (endoffset-startoffset) instead of songlength | ||
1840 | translen=job->targetsong()->songlength_in_samples()*(job->targetsong()->physical_channels()/job->targetsong()->logical_channels()); | ||
1841 | __uint64 totbytestotransfer=translen*bytespersam; | ||
1842 | //transfer_to_hd24(); | ||
1843 | |||
1844 | if (startoffset!=0) { | ||
1845 | if (startoffset>=samplesperblock) { | ||
1846 | samplesinfirstblock=samplesperblock-(startoffset%samplesperblock); | ||
1847 | } else { | ||
1848 | samplesinfirstblock=samplesperblock-startoffset; | ||
1849 | } | ||
1850 | } | ||
1851 | #if (HD24TRANSFERDEBUG==1) | ||
1852 | cout << "go to startoffset " << startoffset << endl; | ||
1853 | #endif | ||
1854 | job->targetsong()->golocatepos(startoffset); | ||
1855 | #if (HD24TRANSFERDEBUG==1) | ||
1856 | cout << "got to startoffset " << startoffset << endl; | ||
1857 | cout << "translen= " << translen << endl; | ||
1858 | #endif | ||
1859 | |||
1860 | __uint32 samplesinblock=samplesinfirstblock; | ||
1861 | if (translen<samplesperblock) | ||
1862 | { | ||
1863 | samplesinfirstblock=translen; | ||
1864 | } | ||
1865 | |||
1866 | __sint64 difseconds=0; | ||
1867 | __sint64 olddifseconds=0; | ||
1868 | __uint64 totbytestransferred=0; // only for multi song transfer- does not apply. | ||
1869 | //deactivate_ui(); | ||
1870 | for (__uint32 samplenum=0; | ||
1871 | samplenum<translen; | ||
1872 | samplenum+=samplesinblock) | ||
1873 | { | ||
1874 | if (transfer_cancel==1) | ||
1875 | { | ||
1876 | //ui_refresh("tohd24_cancel"); | ||
1877 | break; | ||
1878 | } | ||
1879 | #if (HD24TRANSFERDEBUG==1) | ||
1880 | cout << "samnum= " << samplenum << endl; | ||
1881 | #endif | ||
1882 | __uint32 subblockbytes=subblocksize; | ||
1883 | if (translen==samplesinfirstblock) | ||
1884 | { | ||
1885 | #if (HD24TRANSFERDEBUG==1) | ||
1886 | cout << "translen==samplesinfirstblock" << endl; | ||
1887 | subblockbytes=translen*bytespersam; | ||
1888 | samplesinblock=samplesinfirstblock; | ||
1889 | #endif | ||
1890 | } else { | ||
1891 | if (samplenum==0) { | ||
1892 | samplesinblock=samplesinfirstblock; | ||
1893 | } | ||
1894 | else | ||
1895 | { | ||
1896 | samplesinblock=samplesperblock; | ||
1897 | } | ||
1898 | |||
1899 | if (samplenum+samplesinblock>=translen) | ||
1900 | { | ||
1901 | subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam; | ||
1902 | } else { | ||
1903 | if (samplesinblock!=samplesperblock) | ||
1904 | { | ||
1905 | subblockbytes=samplesinblock*bytespersam; | ||
1906 | } | ||
1907 | } | ||
1908 | } | ||
1909 | |||
1910 | #if (HD24TRANSFERDEBUG==1) | ||
1911 | cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl; | ||
1912 | #endif | ||
1913 | |||
1914 | /* | ||
1915 | // disable multipart files for now (this function transfers TO HD24 drives) | ||
1916 | if (wantsplit==1) | ||
1917 | { | ||
1918 | if (((partsamcount+samplesinblock)*bytespersam)>MAXBYTES) /// total filesize reached for current part | ||
1919 | { | ||
1920 | this->closeoutputfiles((SNDFILE**)&filehandle[0],channels); | ||
1921 | partnum++; | ||
1922 | this->openoutputfiles((SNDFILE**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files | ||
1923 | partsamcount=0; | ||
1924 | } | ||
1925 | } | ||
1926 | */ | ||
1927 | for (__uint32 tracknum=0;tracknum<channels;tracknum++) | ||
1928 | { | ||
1929 | if (!(job->targetsong()->trackarmed(tracknum+1))) | ||
1930 | { | ||
1931 | // track not selected for export | ||
1932 | continue; | ||
1933 | } | ||
1934 | __uint32 samsread=0; | ||
1935 | int action=job->trackaction(tracknum+1); | ||
1936 | unsigned int trackchans=1; | ||
1937 | |||
1938 | if (action==0) { /* 0=ERASE */ | ||
1939 | #if (HD24TRANSFERDEBUG==1) | ||
1940 | cout << "track " << tracknum+1 << " marked for erase" << endl; | ||
1941 | |||
1942 | #endif | ||
1943 | samsread=samplesinblock; | ||
1944 | } else { | ||
1945 | if (action==1) | ||
1946 | { | ||
1947 | #if (HD24TRANSFERDEBUG==1) | ||
1948 | cout << "track " << tracknum+1 << " marked for stripe" << endl; | ||
1949 | |||
1950 | #endif | ||
1951 | /* Stripe track with SMPTE/LTC here */ | ||
1952 | |||
1953 | int* buf=audiobuf[tracknum]; | ||
1954 | |||
1955 | for (__uint32 samnum=0;samnum<samplesinblock;samnum++) { | ||
1956 | // smpte stripe: | ||
1957 | buf[samnum]=((job->smptegen->getbit(samplenum+samnum)*2)-1)*2000000; | ||
1958 | } | ||
1959 | /* End of stripe */ | ||
1960 | samsread=samplesinblock; | ||
1961 | } else { | ||
1962 | trackchans=sfinfoin[tracknum].channels; | ||
1963 | if (job->filehandle[tracknum] == NULL) { | ||
1964 | continue; | ||
1965 | } | ||
1966 | samsread=soundfile->sf_read_int( | ||
1967 | job->filehandle[tracknum], | ||
1968 | audiobuf[tracknum], | ||
1969 | samplesinblock*trackchans); | ||
1970 | #if (HD24TRANSFERDEBUG==1) | ||
1971 | cout << "sams read=" | ||
1972 | << samsread | ||
1973 | << endl; | ||
1974 | #endif | ||
1975 | } | ||
1976 | } | ||
1977 | // we replace the deinterlaced data with file audio | ||
1978 | //sf_write_raw(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes); | ||
1979 | |||
1980 | |||
1981 | |||
1982 | // cout << "replace audio block on track " << tracknum+1 << endl; | ||
1983 | |||
1984 | //filehandle[tracknum]; | ||
1985 | |||
1986 | // libsndfile converts all files to 32-bit samples, but we only use 24 bit, | ||
1987 | // so we divide by 256 to shift out the unused 8 bits. | ||
1988 | |||
1989 | __uint32 firstbyte=tracknum*samplesinblock*bytespersam; | ||
1990 | __uint32 whichbyte=firstbyte; | ||
1991 | |||
1992 | int samval; | ||
1993 | for (unsigned int sam=0;sam<samsread;sam+=trackchans) | ||
1994 | { | ||
1995 | int whichsam=sam; | ||
1996 | if (action>2) { | ||
1997 | // multi track | ||
1998 | // use only 24 out of 32 bit | ||
1999 | samval = (audiobuf[tracknum][whichsam+(action-3)])/256; | ||
2000 | } else { | ||
2001 | if (action<2) | ||
2002 | { | ||
2003 | samval=(audiobuf[tracknum][whichsam]); | ||
2004 | } else { | ||
2005 | // action=2 (mono track). | ||
2006 | if (trackchans==1) | ||
2007 | { | ||
2008 | // use the only track | ||
2009 | samval=(audiobuf[tracknum][whichsam])/256; | ||
2010 | } | ||
2011 | else { | ||
2012 | // convert multiple tracks to 1 mono track | ||
2013 | samval=0; | ||
2014 | for (unsigned int whichchan=0;whichchan<trackchans;whichchan++) { | ||
2015 | samval+=(audiobuf[tracknum][whichsam+whichchan])/256; | ||
2016 | } | ||
2017 | // TODO: clip handling | ||
2018 | samval/=trackchans; | ||
2019 | } | ||
2020 | } | ||
2021 | } | ||
2022 | #if (HD24TRANSFERDEBUG==1) | ||
2023 | cout << "whichsam=" << whichsam << " " ;// | ||
2024 | |||
2025 | |||
2026 | cout << "buf[" << tracknum*samplesinblock+(whichsam*bytespersam) << "]="; | ||
2027 | cout << (samval & 0xff) << " " << ((samval>>8) & 0xff) << " " << ((samval>>16) & 0xff) <<"//"; | ||
2028 | if (sam==0) { | ||
2029 | cout << "writing to byte " << whichbyte << " of audiodata " <<endl; | ||
2030 | } | ||
2031 | #endif | ||
2032 | audiodata[whichbyte]=(unsigned char)samval & 0xff; | ||
2033 | audiodata[whichbyte+1]=(unsigned char)(samval>>8) & 0xff; | ||
2034 | audiodata[whichbyte+2]=(unsigned char)(samval>>16) & 0xff; | ||
2035 | whichbyte+=bytespersam; | ||
2036 | } | ||
2037 | // cout << endl; | ||
2038 | |||
2039 | if (transfer_cancel==1) { | ||
2040 | //ui_refresh("tohd24_cancel2"); | ||
2041 | break; | ||
2042 | } | ||
2043 | } | ||
2044 | |||
2045 | // finally we write the audio. the hd24 library will make sure only the relevant | ||
2046 | // tracks will be overwritten and the rest are protected. | ||
2047 | #if (HD24TRANSFERDEBUG==1) | ||
2048 | cout << "1st 30 bytes of track: " << endl; | ||
2049 | for (unsigned int fbyte=0; fbyte<30; fbyte++) { | ||
2050 | cout << audiodata[samplesinblock+fbyte] << " "; | ||
2051 | } | ||
2052 | cout << endl; | ||
2053 | #endif | ||
2054 | //int writesams= (result was not used) | ||
2055 | job->targetsong()->putmtrackaudiodata( | ||
2056 | samplenum+startoffset, | ||
2057 | samplesinblock, | ||
2058 | &audiodata[0], | ||
2059 | hd24song::WRITEMODE_COPY | ||
2060 | ); | ||
2061 | |||
2062 | totbytestransferred+=(samplesinblock*bytespersam); | ||
2063 | |||
2064 | __uint32 pct; // to use for display percentage | ||
2065 | __uint32 oldpct=0; // to use for display percentage | ||
2066 | double dblpct; // to use for ETA calculation | ||
2067 | #if (HD24TRANSFERDEBUG==1) | ||
2068 | cout << "about to calc pct" << endl; | ||
2069 | cout << "totbytestransferred=" << totbytestransferred; | ||
2070 | cout << ", currbytestransferred=" << bytestransferred; | ||
2071 | cout << ", totbytestotransfer=" << totbytestotransfer; | ||
2072 | cout << endl; | ||
2073 | #endif | ||
2074 | |||
2075 | if (translen<100000) { | ||
2076 | pct=(__uint32)(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer)); | ||
2077 | } else { | ||
2078 | pct=(__uint32)((totbytestransferred+bytestransferred)/(totbytestotransfer/100)); | ||
2079 | } | ||
2080 | #if (HD24TRANSFERDEBUG==1) | ||
2081 | cout << "about to calc pct2" << endl; | ||
2082 | #endif | ||
2083 | if (translen<100000) { | ||
2084 | dblpct=(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer)); | ||
2085 | } else { | ||
2086 | dblpct=((totbytestransferred+bytestransferred)/(totbytestotransfer/100)); | ||
2087 | } | ||
2088 | |||
2089 | #if (HD24TRANSFERDEBUG==1) | ||
2090 | cout << "computed pct " << samplenum << endl; | ||
2091 | #endif | ||
2092 | time (&endtime); | ||
2093 | olddifseconds=difseconds; | ||
2094 | difseconds=(long long int)difftime(endtime,starttime); | ||
2095 | |||
2096 | if ((pct!=oldpct) || ((difseconds-olddifseconds)>=1)) | ||
2097 | { | ||
2098 | /* update on percentage change, and also every | ||
2099 | so many samples (to allow frequent enough | ||
2100 | screen updates with large audio files) */ | ||
2101 | oldpct=pct; | ||
2102 | |||
2103 | string* pctmsg=new string("Transferring audio to HD24... %d%%"); | ||
2104 | // TODO: Estimated time remaining goes here | ||
2105 | setstatus(ui,pctmsg,pct); | ||
2106 | delete pctmsg; | ||
2107 | } | ||
2108 | |||
2109 | // fl_check(); covered by setstatus | ||
2110 | } | ||
2111 | |||
2112 | // fl_check(); covered by setstatus | ||
2113 | if (job->smptegen!=NULL) | ||
2114 | { | ||
2115 | // TODO: move to job destructor? | ||
2116 | delete job->smptegen; | ||
2117 | job->smptegen=NULL; | ||
2118 | } | ||
2119 | if (audiodata!=NULL) | ||
2120 | { | ||
2121 | free (audiodata); | ||
2122 | audiodata=NULL; | ||
2123 | } | ||
2124 | for (unsigned int bufnum=0;bufnum<MAXCHANNELS;bufnum++) { | ||
2125 | if (audiobuf[bufnum]!=NULL) { | ||
2126 | memutils::myfree("audiobuf transfer_to_hd24",audiobuf[bufnum]); | ||
2127 | audiobuf[bufnum]=NULL; | ||
2128 | } | ||
2129 | } | ||
2130 | |||
2131 | //end transfer_to_hd24 | ||
2132 | |||
2133 | |||
2134 | |||
2135 | job->targetsong()->stoprecord(); | ||
2136 | |||
2137 | for (unsigned int chnum=1;chnum<=job->targetsong()->logical_channels();chnum++) { | ||
2138 | job->targetsong()->trackarmed(chnum,false); | ||
2139 | } | ||
2140 | this->closeinputfiles((SNDFILE**)&(job->filehandle[0]),job->targetsong()->logical_channels()); | ||
2141 | return totbytestransferred; | ||
2142 | } | ||
2143 | |||