source: trunk/Packages/uos/uos.pas

Last change on this file was 665, checked in by chronos, 45 hours ago
  • Fixed: Playing music on Windows.
File size: 465.7 KB
Line 
1{This unit is part of United Openlibraries of Sound (uos)
2 This is the main uos unit.
3 License : modified LGPL.3
4 Fred van Stappen fiens@hotmail.com }
5
6unit uos;
7
8{$mode objfpc}{$H+}{$inline on}
9{$PACKRECORDS C}
10
11// For custom configuration of directive to compiler ---> uos_define.inc
12{$I uos_define.inc}
13
14interface
15
16uses
17
18{$IF DEFINED (mse)}
19msegui, msethread,
20{$endif}
21
22{$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
23fpg_base, fpg_main,
24{$endif}
25
26{$IF DEFINED (Java)}
27uos_jni,
28{$endif}
29
30{$IF DEFINED (webstream)}
31uos_httpgetthread, Pipes,
32{$ENDIF}
33
34{$IF DEFINED (portaudio)}
35uos_portaudio,
36{$endif}
37
38{$IF DEFINED (xmp)}
39uos_libxmp,
40{$endif}
41
42{$IF DEFINED (sndfile)}
43uos_LibSndFile,
44{$endif}
45
46{$IF DEFINED (mpg123)}
47uos_Mpg123,
48{$endif}
49
50{$IF DEFINED (soundtouch)}
51uos_soundtouch,
52{$endif}
53
54{$IF DEFINED (bs2b)}
55uos_bs2b,
56{$endif}
57
58{$IF DEFINED (noiseremoval)}
59uos_dsp_noiseremoval,
60{$endif}
61
62{$IF DEFINED (neaac)}
63uos_aac,
64{$endif}
65
66{$IF DEFINED (fdkaac)}
67uos_fdkaacdecoder,
68{$endif}
69
70{$IF DEFINED (opus)}
71uos_opusfile,
72{$endif}
73
74{$IF DEFINED (shout)}
75uos_shout, uos_opus,
76{$endif}
77
78{$IF DEFINED (cdrom)}
79uos_cdrom,
80{$endif}
81
82Classes, DynLibs, ctypes, Math, sysutils;
83
84const
85 uos_version : cint32 = 2250411;
86
87{$IF DEFINED (bs2b)}
88 BS2B_HIGH_CLEVEL = (CInt32 (700)) or ( (CInt32 (30)) shl 16);
89 BS2B_MIDDLE_CLEVEL = (CInt32 (500)) or ( (CInt32 (45)) shl 16);
90 BS2B_LOW_CLEVEL = (CInt32 (360)) or ( (CInt32 (60)) shl 16);
91 { Easy crossfeed levels (Obsolete) }
92 BS2B_HIGH_ECLEVEL = (CInt32 (700)) or ( (CInt32 (60)) shl 16);
93 BS2B_MIDDLE_ECLEVEL = (CInt32 (500)) or ( (CInt32 (72)) shl 16);
94 BS2B_LOW_ECLEVEL = (CInt32 (360)) or ( (CInt32 (84)) shl 16);
95 BS2B_DEFAULT_CLEVEL = (CInt32 (700)) or ( (CInt32 (45)) shl 16);
96 BS2B_CMOY_CLEVEL = (CInt32 (700)) or ( (CInt32 (60)) shl 16);
97 BS2B_JMEIER_CLEVEL = (CInt32 (650)) or ( (CInt32 (95)) shl 16);
98{$endif}
99
100{$IF DEFINED (synthesizer)}
101const
102 // musical note ==> frequency in hertz
103 // Latin: Do, Ré, Mi, Fa, Sol, La, Si
104 // Dièse = _d example la0_d
105 la0 = 55.0;
106 la0_d = 58.3;
107 si0 = 61.7;
108 do0 = 65.4;
109 do0_d = 69.3;
110 re0 = 73.4;
111 re0_d = 77.8;
112 mi0 = 82.4;
113 fa0 = 87.3;
114 fa0_d = 92.5;
115 sol0 = 98.0;
116 sol0_d = 103.8;
117 la1 = 110.0;
118 la1_d = 116.5;
119 si1 = 123.5;
120 do1 = 130.8;
121 do1_d = 138.6;
122 re1 = 146.8;
123 re1_d = 155.6;
124 mi1 = 164.8;
125 fa1 = 174.6;
126 fa1_d = 185.0;
127 sol1 = 196.0;
128 sol1_d = 207.7;
129 la2 = 220.0;
130 la2_d = 233.1;
131 si2 = 2246.9;
132 do2 = 261.6;
133 do2_d = 277.2;
134 re2 = 293.7;
135 re2_d = 311.1;
136 mi2 = 329.6;
137 fa2 = 349.2;
138 fa2_d = 370.0;
139 sol2 = 392.0;
140 sol2_d = 415.3;
141 la3 = 440.0;
142 la3_d = 466.2;
143 si3 = 493.9;
144 do3 = 523.3;
145 do3_d = 554.4;
146 re3 = 587.3;
147 re3_d = 622.3;
148 mi3 = 659.3;
149 fa3 = 698.5;
150 fa3_d = 740.0;
151 sol3 = 784.0;
152 sol3_d = 830.6;
153 la4 = 880.0;
154 la4_d = 932.4;
155 si4 = 987.8;
156 do4 = 1046.6;
157 do4_d = 1108.8;
158 re4 = 1174.6;
159 re4_d = 1244.6;
160 mi4 = 1318.6;
161 fa4 = 1397.0;
162 fa4_d = 1480.0;
163 sol4 = 1568.0;
164 sol4_d = 1661.2;
165 la5 = 1760.0;
166
167 // English musique note
168 // A, B, C, D, E, F, G
169 a0 = 55.0;
170 a0_s = 58.3;
171 b0 = 61.7;
172 c0 = 65.4;
173 c0_s = 69.3;
174 d0 = 73.4;
175 d0_s = 77.8;
176 e0 = 82.4;
177 f0 = 87.3;
178 f0_s = 92.5;
179 g0 = 98.0;
180 g0_s = 103.8;
181 a1 = 110.0;
182 a1_s = 116.5;
183 b1 = 123.5;
184 c1 = 130.8;
185 c1_s = 138.6;
186 d1 = 146.8;
187 d1_s = 155.6;
188 e1 = 164.8;
189 f1 = 174.6;
190 f1_s = 185.0;
191 g1 = 196.0;
192 g1_s = 207.7;
193 a2 = 220.0;
194 a2_s = 233.1;
195 b2 = 2246.9;
196 c2 = 261.6;
197 c2_s = 277.2;
198 d2 = 293.7;
199 d2_s = 311.1;
200 e2 = 329.6;
201 f2 = 349.2;
202 f2_s = 370.0;
203 g2 = 392.0;
204 g2_s = 415.3;
205 a3 = 440.0;
206 a3_s = 466.2;
207 b3 = 493.9;
208 c3 = 523.3;
209 c3_s = 554.4;
210 d3 = 587.3;
211 d3_s = 622.3;
212 e3 = 659.3;
213 f3 = 698.5;
214 f3_s = 740.0;
215 g3 = 784.0;
216 g3_s = 830.6;
217 a4 = 880.0;
218 a4_s = 932.4;
219 b4 = 987.8;
220 c4 = 1046.6;
221 c4_s = 1108.8;
222 d4 = 1174.6;
223 d4_s = 1244.6;
224 e4 = 1318.6;
225 f4 = 1397.0;
226 f4_s = 1480.0;
227 g4 = 1568.0;
228 g4_s = 1661.2;
229 a5 = 1760.0;
230{$endif}
231
232{$IF DEFINED (shout)}
233 cFRAME_SIZE = 960;
234 cSAMPLE_RATE = 48000;
235 cAPPLICATION = OPUS_APPLICATION_AUDIO;
236 cBITRATE = 64000;
237 cMAX_FRAME_SIZE = 6 * 960;
238 cMAX_PACKET_SIZE = 3 * 1276;
239{$endif}
240
241type
242 TDummyThread = class (TThread)
243 protected
244 procedure execute;
245 override;
246 end;
247
248{$IF DEFINED (mse)}
249{$else}
250
251type
252 TuosThread = class (TThread)
253 protected
254 procedure execute;
255 override;
256 public
257 theparent : Tobject;
258
259 constructor Create (CreateSuspended: boolean; AParent: TObject;
260 Const StackSize: SizeUInt = DefaultStackSize);
261 overload;
262 virtual;
263 procedure DoTerminate;
264 override;
265 end;
266{$endif}
267
268type
269 TDArFloat = array of cfloat;
270 TDArShort = array of cInt16;
271 TDArLong = array of cInt32;
272
273 TDArPARFloat = array of TDArFloat;
274 TDArIARFloat = array of TDArPARFloat;
275
276 PDArFloat = ^TDArFloat;
277 PDArShort = ^TDArShort;
278 PDArLong = ^TDArLong;
279
280 {$IF not DEFINED (windows)}
281 THandle = pointer;
282 TArray = single;
283{$endif}
284
285type
286 Tuos_BufferInfos = record
287 SampleRate: CDouble;
288 SampleRateRoot: CDouble;
289 SampleFormat: cint32;
290 Channels: cint32;
291 Filename: UTF8String;
292 Title: UTF8String;
293 Copyright: UTF8String;
294 Software: UTF8String;
295 Artist: UTF8String;
296 Comment: UTF8String;
297 Date: string;
298 Tag: array[0..2] of char;
299 Album: UTF8String;
300 Genre: string;
301 Track: string;
302 HDFormat: cint32;
303 Sections: cint32;
304 Encoding: cint32;
305 bitrate: cint32;
306 Length: cint32;
307 // length samples total
308 LibOpen: shortint;
309 Ratio: byte;
310 end;
311
312type
313{$if not defined (fs32bit)}
314 Tcount_t = cint64; { used for file sizes }
315{$else}
316 Tcount_t = cint32;
317{$endif}
318
319type
320 Tuos_LoadResult = record
321 PAloadError: shortint;
322 SFloadError: shortint;
323 MPloadError: shortint;
324 PCloadError: shortint;
325 STloadError: shortint;
326 BSloadError: shortint;
327 AAloadError: shortint;
328 OPloadError: shortint;
329 XMloadError: shortint;
330 FAloadError: shortint;
331 PAinitError: shortint;
332 MPinitError: shortint;
333 end;
334
335type
336 Tuos_Init = class (TObject)
337 public
338 // for global pausing
339 evGlobalPause: PRTLEvent;
340
341 constructor Create;
342 private
343
344 PA_FileName: pchar;
345 // PortAudio
346 SF_FileName: pchar;
347 // SndFile
348 MP_FileName: pchar;
349 // Mpg123
350 AA_FileName : PChar;
351 // Faad
352 M4_FileName : PChar;
353 // Mp4ff
354 OF_FileName : PChar;
355 // opusfile
356 XM_FileName : PChar;
357 // XMP
358 FA_FileName : PChar;
359 // Fdkaac
360 Plug_ST_FileName: pchar;
361 // Plugin SoundTouch + GetBMP
362 Plug_BS_FileName: pchar;
363 // Plugin bs2b
364
365{$IF DEFINED (portaudio)}
366 DefDevOut: PaDeviceIndex;
367 DefDevOutInfo: PPaDeviceInfo;
368 DefDevOutAPIInfo: PPaHostApiInfo;
369 DefDevIn: PaDeviceIndex;
370 DefDevInInfo: PPaDeviceInfo;
371 DefDevInAPIInfo: PPaHostApiInfo;
372{$endif}
373
374 function loadlib: cint32;
375 procedure unloadlib;
376 procedure unloadlibCust (PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
377 function InitLib: cint32;
378 procedure unloadPlugin (PluginName: Pchar);
379 end;
380
381type
382 Tuos_DeviceInfos = record
383 DeviceNum: cint32;
384 DeviceName: UTF8String;
385 DeviceType: UTF8String;
386 DefaultDevIn: boolean;
387 DefaultDevOut: boolean;
388 ChannelsIn: cint32;
389 ChannelsOut: cint32;
390 SampleRate: CDouble;
391 LatencyHighIn: CDouble;
392 LatencyLowIn: CDouble;
393 LatencyHighOut: CDouble;
394 LatencyLowOut: CDouble;
395 HostAPIName: UTF8String;
396 end;
397
398type
399 // corresponds to WAVEFORMATEX structure
400 Tuos_WaveHeaderChunk = packed record
401 wFormatTag : Word;
402 wChannels : Word;
403 wSamplesPerSec : cuint32;
404 // Sample Rate
405 wAvgBytesPerSec : cuint32;
406 // (wSamplesPerSec * wBitsPerSample * wChannels) / 8 => Byte Rate
407 wBlockAlign : Word;
408 // (wBitsPerSample * wChannels) / 8 => Bytes total per Sample
409 wBitsPerSample : Word;
410 wcbSize : Word;
411 end;
412
413type
414 Tuos_FileBuffer = record
415 ERROR: word;
416 wSamplesPerSec: cint32;
417 wBitsPerSample: word;
418 wChannels: word;
419 FileFormat: shortint;
420 Data: TFileStream;
421 DataMS: TMemoryStream;
422 end;
423
424type
425 Tuos_Data = record
426 // Global data
427 Enabled: boolean;
428
429 TypePut: shortint;
430 // -1 : nothing.
431 // for Input : 0: from audio encoded file, 1: from input device (like mic),
432 // 2: from internet audio stream, 3: from Synthesizer, 4: from memory buffer,
433 // 5: from endless-muted, 6: from decoded memorystream
434 //
435
436
437
438 // for Output : 0: into wav file from filestream, 1: into output device Portaudio, 2: into stream server,
439 // 3: into memory buffer, 4: into wav file from memorystream, 5: into memorystream,
440 // 6: into ogg file from filestream, 7: into ogg memorystream
441
442 Seekable: boolean;
443 Status: byte;
444 Buffer: TDArFloat;
445 MemoryBuffer: TDArFloat;
446 MemoryStream : Tmemorystream;
447
448 posmem : longint;
449
450 {$IF DEFINED (opus)}
451 BufferTMP: tbytes;
452 {$endif}
453
454 DSPVolumeIndex : cint32;
455 DSPNoiseIndex : cint32;
456 VLeft, VRight: double;
457 hasfilters : boolean;
458 nbfilters : cint32;
459 incfilters : cint32;
460 levelfilters : string;
461 levelfiltersar : TDArFloat;
462 PositionEnable : shortint;
463 LevelEnable : shortint;
464 LevelLeft, LevelRight: cfloat;
465 levelArrayEnable : shortint;
466
467{$IF DEFINED (synthesizer)}
468 LookupTableLeft, LookupTableRight: array [0..1023] of CFloat;
469 PosInTableLeft, PosInTableRight: Double;
470 typLsine, typRsine: cint32;
471 freqLsine, freqRsine: cfloat;
472 dursine, posdursine: cint32;
473 harmonic: cint32;
474 evenharm: shortint;
475{$endif}
476
477{$if defined (cpu64)}
478 Wantframes: Tcount_t;
479 OutFrames: Tcount_t;
480{$else}
481 Wantframes: cint32;
482 OutFrames: cint32;
483{$endif}
484
485 SamplerateRoot: CDouble;
486 SampleRate: CDouble;
487 SampleFormat: cint32;
488 Channels: cint32;
489 lastbuf: shortint;
490
491 // audio file data
492 HandleSt: pointer;
493 {$IF DEFINED (opus)}
494 HandleOP: TOpusFile;
495 {$endif}
496 Filename: UTF8String;
497 Title: UTF8String;
498 Copyright: UTF8String;
499 Software: UTF8String;
500 Artist: UTF8String;
501 Comment: UTF8String;
502 Date: string;
503 Tag: array[0..2] of char;
504 Album: UTF8String;
505 Genre: string;
506 Track: string;
507 HDFormat: cint32;
508 {$IF DEFINED (sndfile)}
509 Frames: Tcount_t;
510 {$else}
511 Frames: cint32;
512 {$endif}
513 Sections: cint32;
514 Encoding: cint32;
515 bitrate: cint32;
516 Length: cint32;
517 // length samples total
518 LibOpen: shortint;
519 // -1: nothing open, 0: sndfile open, 1: mpg123 open, 2: aac open, 3: cdrom, 4: opus, 5: xmp
520 Ratio: byte;
521 // if mpg123 or aac then ratio := 2
522
523 BPM : cfloat;
524 numbuf : integer;
525 Output: cint32;
526
527 {$if defined (cpu64)}
528 // TO CHECK
529 Position: cint32;
530 Poseek: cint32;
531 {$else}
532 Position: cint32;
533 Poseek: cint32;
534 {$endif}
535
536 end;
537
538type
539 TArray01 = array[0..1] of cfloat;
540
541 Tuos_FFT = class (TObject)
542 public
543
544 TypeFilterL, TypeFilterR: byte;
545 LowFrequencyL, HighFrequencyL: cfloat;
546 LowFrequencyR, HighFrequencyR: cfloat;
547 GainL, GainR: cfloat;
548
549 // Left
550 a3, a32: array[0..2] of cfloat;
551 b2, x0, x1, y0, y1, b22, x02, x12, y02, y12: TArray01;
552 C, D, C2, D2 : cfloat;
553
554 // Right
555 a3R, a32R: array[0..2] of cfloat;
556 b2R, x0R, x1R, y0R, y1R, b22R, x02R, x12R, y02R, y12R: TArray01;
557 CR, DR, C2R, D2R : cfloat;
558
559 AlsoBuf: boolean;
560 VirtualBuffer: TDArFloat;
561 levelstring : string;
562
563 {$IF DEFINED (noiseremoval)}
564 FNoise : TuosNoiseRemoval;
565 {$endif}
566
567 constructor Create;
568 end;
569
570type
571 TFunc = function (Var Data: Tuos_Data; Var FFT: Tuos_FFT): TDArFloat;
572
573 {$if DEFINED (java)}
574 TProc = JMethodID;
575 {$else}
576 TProc = procedure of object;
577 TPlayerProc = procedure (PlayerIndex: cint32) of object;
578 {$endif}
579
580 TProcOnly = procedure ;
581
582 {$IF DEFINED (bs2b) or DEFINED (soundtouch)}
583 TPlugFunc = function (bufferin: TDArFloat; plugHandle: THandle; Abs2bd : Tt_bs2bdp; Var inputData:
584 Tuos_Data;
585 param1: float; param2: float; param3: float; param4: float;
586 param5: float; param6: float; param7: float; param8: float): TDArFloat;
587 {$endif}
588
589type
590 Tuos_DSP = class (TObject)
591 public
592 Enabled: boolean;
593 // function to execute before buffer is filled
594 BefFunc: TFunc;
595 // function to execute after buffer is filled
596 AftFunc: TFunc;
597 // function to execute at end of thread;
598 EndFunc: TFunc;
599 // External Procedure of object to synchronize after buffer is filled
600 LoopProc: TProc;
601 // for FFT
602 fftdata: Tuos_FFT;
603
604 {$IF DEFINED (Java)}
605 procedure LoopProcjava;
606 {$endif}
607
608 constructor Create;
609
610 destructor Destroy;
611 override;
612
613 end;
614
615type
616 Tuos_InStream = class (TObject)
617 {$IF DEFINED (webstream)}
618 private
619 procedure UpdateIcyMetaInterval;
620 {$endif}
621 public
622 Data: Tuos_Data;
623 DSP: array of Tuos_DSP;
624
625 MemoryStreamDec : TMemoryStream;
626
627 {$IF DEFINED (neaac)}
628 AACI: TAACInfo;
629 {$endif}
630
631 {$IF DEFINED (cdrom)}
632 pCD: PCDROMInfo;
633 {$endif}
634
635 // for web streaming
636 {$IF DEFINED (webstream)}
637 httpget: TThreadHttpGetter;
638 // threaded http getter
639 {$IF DEFINED (windows)}
640 {$if defined (cpu64)}
641 InHandle : Qword;
642 OutHandle: Qword;
643 {$else}
644 InHandle : longword;
645 OutHandle: longword;
646 {$ENDIF}
647 {$else}
648 InHandle : cint32;
649 OutHandle: cint32;
650 {$endif}
651 InPipe: TInputPipeStream;
652 OutPipe: TOutputPipeStream;
653 {$ENDIF}
654 {$IF DEFINED (portaudio)}
655 PAParam: PaStreamParameters;
656 {$endif}
657 LoopProc: TProc;
658 // External Procedure of object to synchronize after buffer is filled
659
660 {$IF DEFINED (Java)}
661 procedure LoopProcjava;
662 {$endif}
663
664 constructor Create;
665
666 destructor Destroy;
667 override;
668 end;
669
670type
671 Tuos_OutStream = class (TObject)
672 public
673 Data: Tuos_Data;
674 BufferOut: PDArFloat;
675 MemorySteamOut: TMemoryStream;
676 DSP: array of Tuos_DSP;
677 {$IF DEFINED (portaudio)}
678 PAParam: PaStreamParameters;
679 {$endif}
680 {$IF DEFINED (shout)}
681 encoder: TOpusEncoder;
682 cbits: array [0..cMAX_PACKET_SIZE - 1] of Byte;
683 // cbits: tbytes;
684 {$endif}
685 FileBuffer: Tuos_FileBuffer;
686 LoopProc: TProc;
687 // External Procedure of object to synchronize after buffer is filled
688 {$IF DEFINED (Java)}
689 procedure LoopProcjava;
690 {$endif}
691
692 constructor Create;
693
694 destructor Destroy;
695 override;
696 end;
697
698 Tuos_Plugin = class (TObject)
699 public
700 Enabled: boolean;
701 Name: string;
702 PlugHandle: THandle;
703
704 {$IF DEFINED (bs2b) or DEFINED (soundtouch)}
705 Abs2b : Tt_bs2bdp;
706 PlugFunc: TPlugFunc;
707 {$endif}
708 param1: float;
709 param2: float;
710 param3: float;
711 param4: float;
712 param5: float;
713 param6: float;
714 param7: float;
715 param8: float;
716 Buffer: TDArFloat;
717
718 constructor Create;
719 end;
720
721type
722
723 { Tuos_Player }
724
725 Tuos_Player = class (tobject)
726 protected
727 {$IF DEFINED (mse)}
728 thethread : tmsethread;
729 {$else}
730 thethread : TuosThread;
731 {$endif}
732 evPause: PRTLEvent;
733 // for pausing
734 procedure ReadFile (x : integer);
735 {$IF DEFINED (webstream)}
736 procedure ReadUrl (x : integer);
737 {$endif}
738 {$IF DEFINED (synthesizer)}
739 procedure ReadSynth (x : integer);
740 procedure FillLookupTable (x, typewave, channel,
741 AHarmonics: Integer; EvenHarmonics: shortint);
742 {$endif}
743 procedure ReadEndless (x : integer);
744 procedure ReadMem (x : integer);
745 procedure ReadMemDec (x : integer);
746 {$IF DEFINED (portaudio)}
747 procedure ReadDevice (x : integer);
748 {$endif}
749 procedure WriteOutPlug (x:integer; x2 : integer);
750 procedure WriteOut (x:integer; x2 : integer);
751 procedure CheckIfPaused;
752 procedure DoBeginMethods;
753 procedure DoLoopBeginMethods;
754 procedure DoLoopEndMethods;
755 procedure DoArrayLevel (x: integer);
756 procedure DoSeek (x: integer);
757 procedure DoDSPinBeforeBufProc (x: integer);
758 procedure DoDSPinAfterBufProc (x: integer);
759 procedure DoDSPOutAfterBufProc (x: integer);
760 procedure DoMainLoopProc (x: integer);
761 procedure SeekIfTerminated;// inline;
762 procedure DoTerminateNoFreePlayer;
763 procedure DoTerminatePlayer;
764 procedure DoEndProc;
765 procedure EndProcExecute;
766
767 {$IF DEFINED (mse)}
768 function execute (thread: tmsethread): integer;
769 inline;
770 {$endif}
771
772 public
773 isAssigned: boolean;
774 isGlobalPause: boolean;
775 Status: cint32;
776
777 //if use -1 value (default) -> not alterate uosPlayers[],..
778 Index: cint32;
779
780 // to check, needed for filetobuf
781 intobuf : boolean;
782
783 // -1 infinite loop; 0 no loop; > 0 n-loop
784 NLooped : Integer;
785
786 // Do not free the player at end of thread.
787 NoFree : boolean;
788
789 // External procedure of object to execute at begin of thread
790 BeginProc: TProc;
791
792 // External procedure of object to execute at each begin of loop
793 LoopBeginProc: TProc;
794
795 // External procedure of object to execute at each end of loop
796 LoopEndProc: TProc;
797
798 // Procedure of object to execute at end of thread
799 EndProc: TPlayerProc;
800
801 // Procedure to execute at end of thread (not of object)
802 EndProcOnly: TProcOnly;
803
804 StreamIn: array of Tuos_InStream;
805 StreamOut: array of Tuos_OutStream;
806 PlugIn: array of Tuos_Plugin;
807
808 {$IF DEFINED (Java)}
809 PEnv : PJNIEnv;
810 Obj: JObject;
811 procedure beginprocjava;
812 procedure endprocjava;
813 procedure LoopBeginProcjava;
814 procedure LoopEndProcjava;
815 {$endif}
816
817 constructor create ();
818
819 destructor Destroy;
820 override;
821
822 function IsLooped: Boolean;
823
824 // Set the RTL Events Global (will pause/start/replay all the players synchro with same rtl event))
825 // result : true if set ok.
826 function SetGlobalEvent (isenabled : boolean) : boolean;
827
828 // Audio methods
829
830 // Start playing with free at end as parameter and assign loop
831 procedure PlayEx (no_free: Boolean; nloop: Integer; paused: boolean= false);
832
833 // Start playing with loop
834 procedure Play (nloop: Integer = 0);
835
836 // Start play paused with loop
837 procedure PlayPaused (nloop: Integer = 0);
838
839 // Resume playing after pause
840 procedure RePlay ();
841
842 // Stop playing and free thread
843 procedure Stop ();
844
845 // Pause playing
846 procedure Pause ();
847
848 // Starting but do not free the player after stop with loop
849 procedure PlayNoFree (nloop: Integer = 0);
850
851 // Start play paused with loop but not free player at end
852 procedure PlayNoFreePaused (nloop: Integer = 0);
853
854 // Free the player: works only when PlayNoFree () was called.
855 procedure FreePlayer ();
856
857 {$IF DEFINED (portaudio)}
858 // Add an Output into Device Output
859 // Device ( -1 is default device )
860 // Latency ( -1 is latency suggested )
861 // SampleRate : default: -1 (44100)
862 // Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
863 // SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
864 // FramesCount : default: -1 (= 65536)
865 // ChunkCount : default: -1 (= 512)
866 // result : Output Index in array -1 = error
867 // example : OutputIndex1 := AddIntoDevOut (-1,-1,-1,-1,0,-1,-1);
868 function AddIntoDevOut (Device: cint32; Latency: CDouble;
869 SampleRate: CDouble; Channels: cint32; SampleFormat: cint32;
870 FramesCount: cint32; ChunkCount: cint32 ): cint32;
871{$endif}
872
873 // Add an Output into audio wav file with custom parameters from TFileStream
874 // FileName : filename of saved audio wav file
875 // SampleRate : default: -1 (44100)
876 // Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
877 // SampleFormat : default: -1 (2:Int16) ( 1:Int32, 2:Int16)
878 // FramesCount : default: -1 (= 4096)
879 // FileFormat : default: -1 (wav) (0:wav, 1:pcm, 2:custom, 3:ogg);
880 // result : Output Index in array -1 = error
881 // example : OutputIndex1 := AddIntoFile (edit5.Text,-1,-1, 0, -1, -1);
882 function AddIntoFile (Filenamepath: PChar; SampleRate: CDouble;
883 Channels: cint32; SampleFormat: cint32; FramesCount: cint32; FileFormat
884 : cint32): cint32;
885
886 // Add an Output into audio wav file with custom parameters from TMemoryStream
887 // FileName : filename of saved audio wav file
888 // SampleRate : default: -1 (44100)
889 // Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
890 // SampleFormat : default: -1 (2:Int16) ( 1:Int32, 2:Int16)
891 // FramesCount : default: -1 (= 4096)
892 // FileFormat : default: -1 (wav) (0:wav, 1:pcm, 2:custom);
893 // result : Output Index in array -1 = error
894 // example : OutputIndex1 := AddIntoFileFromBuf (edit5.Text,-1,-1, 0, -1);
895 function AddIntoFileFromMem (Filenamepath: PChar; SampleRate: CDouble;
896 Channels: LongInt; SampleFormat: LongInt; FramesCount: LongInt;
897 FileFormat: cint32): LongInt;
898
899 // Add an Output into memory buffer
900 // outmemory : pointer of buffer to use to store memory.
901 // example : OutputIndex1 := AddIntoMemoryBuffer (bufmemory);
902 function AddIntoMemoryBuffer (outmemory: PDArFloat) : cint32;
903
904 // Add an Output into TMemoryStream
905 // outmemory : pointer of buffer to use to store memory.
906 // SampleRate : default: -1 (44100)
907 // SampleFormat : default: -1 (0:float32) ( 1:Int32, 2:Int16)
908 // Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
909 // FramesCount : default: -1 (= 65536)
910 function AddIntoMemoryBuffer (outmemory: PDArFloat; SampleRate: CDouble; SampleFormat:
911 LongInt;
912 Channels: LongInt; FramesCount: LongInt): LongInt;
913
914 // Add an Output into TMemoryStream
915 // MemoryStream : the TMemoryStream to use to store memory.
916 // SampleRate : default: -1 (44100)
917 // SampleFormat : default: -1 (2:Int16) ( 1:Int32, 2:Int16)
918 // Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
919 // FramesCount : default: -1 (= 4096)
920 // AudioFormat : default: -1 (wav) (0:wav, 1:ogg);
921 function AddIntoMemoryStream (Var MemoryStream: TMemoryStream; SampleRate: CDouble;
922 SampleFormat: LongInt; Channels: LongInt; FramesCount: LongInt;
923 AudioFormat: cint32): LongInt;
924
925 {$IF DEFINED (shout)}
926 // Add an Output into an IceCast server for audio-web-streaming
927 // SampleRate : default: -1 (48000)
928 // Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
929 // SampleFormat : -1 default: float32 : (0:float32, 1:Int16)
930 // EncodeType : default: -1 (0:Music) (0: Music, 1:Voice)
931 // Port : default: -1 (= 8000)
932 // Host : default: 'def' (= '127.0.0.1')
933 // User : default: 'def' (= 'source')
934 // Password : default: 'def' (= 'hackme')
935 // MountFile : default: 'def' (= '/example.opus')
936 // result : Output Index in array -1 = error
937 function AddIntoIceServer (SampleRate : CDouble; Channels: cint; SampleFormat: cint;
938 EncodeType: cint; Port: cint; Host: pchar; User: pchar; Password:
939 pchar; MountFile :pchar): cint32;
940 {$endif}
941
942{$IF DEFINED (portaudio)}
943 // Add an Input from Device Input with custom parameters
944 // Device ( -1 is default Input device )
945 // Latency ( -1 is latency suggested ) )
946 // SampleRate : default: -1 (44100)
947 // OutputIndex : Output index of used output
948 // -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
949 // SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
950 // FramesCount : default: -1 (4096)
951 // ChunkCount : default: -1 (= 512)
952 // result : otherwise Output Index in array -1 = error
953 // example : OutputIndex1 := AddFromDevice (-1,-1,-1,-1,-1, -1);
954 function AddFromDevIn (Device: cint32; Latency: CDouble;
955 SampleRate: CDouble; OutputIndex: cint32;
956 SampleFormat: cint32; FramesCount : cint32; ChunkCount: cint32): cint32;
957{$endif}
958
959 // Add an input from Endless Muted dummy sine wav
960 // FramesCount = FramesCount of input-to-follow
961 // Channels = Channels of input-to-follow.
962 function AddFromEndlessMuted (Channels : cint32; FramesCount: cint32): cint32;
963
964 // Get current buffer
965 function InputGetBuffer (InputIndex: cint32): TDArFloat;
966
967{$IF DEFINED (synthesizer)}
968 // Add an input from Synthesizer with custom parameters
969 // Channels: default: -1 (2) (1 = mono, 2 = stereo)
970 // WaveTypeL: default: -1 (0) (0 = sine-wave, 1 = square-wave, 2= triangle, 3=sawtooth used for mono and stereo)
971 // WaveTypeR: default: -1 (0) (0 = sine-wave, 1 = square-wave, 2= triangle, , 3=sawtooth used for stereo, ignored for mono)
972 // FrequencyL: default: -1 (440 htz) (Left frequency, used for mono)
973 // FrequencyR: default: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
974 // VolumeL: default: -1 (= 1) (from 0 to 1) => volume left
975 // VolumeR: default: -1 (= 1) (from 0 to 1) => volume rigth (ignored for mono)
976 // Duration: default: -1 (= 1000) => duration in msec (0 = endless)
977 // NbHarmonics: default: -1 (= 0) Number of Harmonics
978 // EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
979 // OutputIndex: Output index of used output
980 // -1: all output, -2: no output, other cint32 refer to
981 // an existing OutputIndex
982 // (if multi-output then OutName = name of each output separated by ';')
983 // SampleFormat: default: -1 (0: Float32) (0: Float32, 1:Int32, 2:Int16)
984 // SampleRate: default: -1 (44100)
985 // FramesCount: -1 default: 1024
986 // result: Input Index in array -1 = error
987 function AddFromSynth (Channels: integer; WaveTypeL, WaveTypeR: shortint;
988 FrequencyL, FrequencyR: float; VolumeL, VolumeR: float;
989 duration : cint32; NbHarmonics: cint32; EvenHarmonics: cint32;
990 OutputIndex: cint32; SampleFormat: cint32; SampleRate: CDouble;
991 FramesCount : cint32): cint32;
992
993 // InputIndex: one existing input index
994 // WaveTypeL: do not change: -1 (0 = sine-wave 1 = square-wave, 2= triangle, 3=sawtooth used for mono and stereo)
995 // WaveTypeR: do not change: -1 (0 = sine-wave 1 = square-wave, 2= triangle, 3=sawtooth used for stereo, ignored for mono)
996 // FrequencyL: do not change: -1 (Left frequency, used for mono)
997 // FrequencyR: do not change: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
998 // VolumeL: do not change: -1 (= 1) (from 0 to 1) => volume left
999 // VolumeR: do not change: -1 (from 0 to 1) => volume rigth (ignored for mono)
1000 // Duration: in msec (-1 = do not change)
1001 // NbHarmonic: Number of Harmonics (-1 not change)
1002 // EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
1003 // Enable: true or false;
1004 procedure InputSetSynth (InputIndex: cint32; WaveTypeL, WaveTypeR: shortint;
1005 FrequencyL, FrequencyR: float; VolumeL, VolumeR: float; duration:
1006 cint32;
1007 NbHarmonic: cint32; EvenHarmonics: cint32; Enable: boolean);
1008{$endif}
1009
1010 // Add an input from audio file with custom parameters
1011 // FileName : filename of audio file
1012 //
1013 // OutputIndex : Output index of used output
1014 // -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
1015 // SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
1016 // FramesCount : default: -1 (4096)
1017 // result : Input Index in array -1 = error
1018 // example : InputIndex1 := AddFromFile (edit5.Text,-1,0,-1);
1019 function AddFromFile (Filename: Pchar; OutputIndex: cint32;
1020 SampleFormat: cint32; FramesCount: cint32): cint32;
1021
1022 // Add an input from audio file and store it into memory with custom parameters
1023 // FileName : filename of audio file
1024 // OutputIndex : Output index of used output
1025 // -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
1026 // SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
1027 // FramesCount : default: -1 (4096)
1028 // numbuf : number of buffer to add to outmemory (default: -1 = all, otherwise number max of buffers)
1029 // result : Input Index in array -1 = error
1030 // example : InputIndex1 := AddFromFileIntoMemory (edit5.Text,-1,0,-1, -1);
1031 function AddFromFileIntoMemory (Filename: Pchar; OutputIndex: cint32;
1032 SampleFormat: cint32; FramesCount: cint32; numbuf : cint): cint32;
1033
1034 // Add an input from memory buffer with custom parameters
1035 // MemoryBuffer : the buffer
1036 // Bufferinfos : infos of the buffer
1037 // OutputIndex : Output index of used output
1038 // -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
1039 // Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
1040 // SampleRate : default: -1 (44100)
1041 // FramesCount : default: -1 (4096)
1042 // FramesCount : default: -1 (65536 div Channels)
1043 // result : Input Index in array -1 = error
1044 // example : InputIndex1 := AddFromMemoryBuffer (mybuffer, buffinfos,-1,1024);
1045 function AddFromMemoryBuffer (Var MemoryBuffer: TDArFloat; Var Bufferinfos: Tuos_bufferinfos;
1046 OutputIndex: cint32; FramesCount: cint32): cint32;
1047
1048 // MemoryStream : Memory stream of encoded audio.
1049 // TypeAudio : default: -1 --> 0 (0: flac, ogg, wav; 1: mp3; 2:opus)
1050 // OutputIndex : Output index of used output
1051 // -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
1052 // SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
1053 // FramesCount : default: -1 (4096)
1054 // result : Input Index in array -1 = error
1055 // example : InputIndex1 := AddFromMemoryStream (mymemorystream,-1,-1,0,1024);
1056 function AddFromMemoryStream (Var MemoryStream: TMemoryStream;
1057 TypeAudio: cint32; OutputIndex: cint32; SampleFormat: cint32;
1058 FramesCount: cint32): cint32;
1059
1060 // MemoryStream : Memory-stream of decoded audio (like created by AddIntoMemoryStream)
1061 // Bufferinfos : infos of the Memory-stream
1062 // OutputIndex : Output index of used output
1063 // -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
1064 // FramesCount : default: -1 (4096)
1065 // result : Input Index in array -1 = error
1066 function AddFromMemoryStreamDec (Var MemoryStream: TMemoryStream; Var Bufferinfos:
1067 Tuos_bufferinfos;
1068 OutputIndex: cint32; FramesCount: cint32): cint32;
1069
1070{$IF DEFINED (webstream)}
1071 // Add an Input from Audio URL
1072 // URL : URL of audio file
1073 // OutputIndex : OutputIndex of existing Output
1074 // -1: all output, -2: no output, other cint32 : existing Output
1075 // SampleFormat : -1 default: Int16 (0: Float32, 1:Int32, 2:Int16)
1076 // FramesCount : default: -1 (4096)
1077 // AudioFormat : default: -1 (auto-find) (0: mp3, 1: opus, 2:aac)
1078 // ICYon : ICY data on/off
1079 // example : InputIndex := AddFromURL ('http://someserver/somesound.mp3',-1,-1,-1,-1,false);
1080 function AddFromURL (URL: PChar; OutputIndex: cint32;
1081 SampleFormat: cint32; FramesCount: cint32; AudioFormat: cint32; ICYon:
1082 boolean): cint32;
1083{$ENDIF}
1084
1085 // Add a plugin , result is PluginIndex
1086 // SampleRate : default: -1 (44100)
1087 // Channels : default: -1 (2:stereo) (1:mono, 2:stereo, ...)
1088 // 'soundtouch' 'getbpm' and 'bs2b' PlugName are registred.
1089 function AddPlugin (PlugName: Pchar; SampleRate: CDouble;
1090 Channels: cint32): cint32;
1091
1092{$IF DEFINED (soundtouch)}
1093 // PluginIndex : PluginIndex Index of an existing Plugin.
1094 procedure SetPluginSoundTouch (PluginIndex: cint32; Tempo: cfloat;
1095 Pitch: cfloat; Enable: boolean);
1096
1097 // PluginIndex : PluginIndex Index of an existing Plugin.
1098 // numofframes: number of frames to analyse (-1 = 512 x frames)
1099 // loop: do new detection after previous.
1100 procedure SetPluginGetBPM (PluginIndex: cint32; numofframes: integer; loop : boolean;
1101 Enable: boolean);
1102{$endif}
1103
1104{$IF DEFINED (bs2b)}
1105 // PluginIndex : PluginIndex Index of an existing Plugin.
1106 procedure SetPluginBs2b (PluginIndex: cint32; level: CInt32; fcut: CInt32;
1107 feed: CInt32; Enable: boolean);
1108{$endif}
1109
1110 // Get the status of the player : 0 => has stopped, 1 => is running, 2 => is paused,
1111 // -1 => error or not yet played, only created.
1112 function GetStatus () : cint32;
1113
1114 // change position in sample
1115 procedure InputSeek (InputIndex: cint32; pos: Tcount_t);
1116
1117 // change position in seconds
1118 procedure InputSeekSeconds (InputIndex: cint32; pos: cfloat);
1119
1120 // change position in time format
1121 procedure InputSeekTime (InputIndex: cint32; pos: TTime);
1122
1123 // set enable true or false
1124 procedure InputSetEnable (InputIndex: cint32; enabled: boolean);
1125
1126 // InputIndex : InputIndex of existing input
1127 // result : Length of Input in samples
1128 function InputLength (InputIndex: cint32): cint32;
1129
1130 // InputIndex : InputIndex of existing input
1131 // result : Length of Input in seconds
1132 function InputLengthSeconds (InputIndex: cint32): cfloat;
1133
1134 // InputIndex : InputIndex of existing input
1135 // result : Length of Input in time format
1136 function InputLengthTime (InputIndex: cint32): TTime;
1137
1138 // InputIndex : InputIndex of existing input
1139 // result : current postion in sample
1140 function InputPosition (InputIndex: cint32): cint32;
1141
1142 // InputIndex : InputIndex of existing input
1143 // result : current postion of Input in seconds
1144 function InputPositionSeconds (InputIndex: cint32): float;
1145
1146 // InputIndex : InputIndex of existing input
1147 // result : current postion of Input in time format
1148 function InputPositionTime (InputIndex: cint32): TTime;
1149
1150 // set number of frames to be done. (useful for recording and level precision)
1151 procedure InputSetFrameCount (InputIndex: cint32; framecount : cint32);
1152
1153 // set level calculation (default is 0)
1154 // 0 => no calcul
1155 // 1 => calcul before all DSP procedures.
1156 // 2 => calcul after all DSP procedures.
1157 // 3 => calcul before and after all DSP procedures.
1158 procedure InputSetLevelEnable (InputIndex: cint32; levelcalc : cint32);
1159
1160 // set position calculation (default is 0)
1161 // 0 => no calcul
1162 // 1 => calcul of position.
1163 procedure InputSetPositionEnable (InputIndex: cint32; poscalc : cint32);
1164
1165 // set add level calculation in level-array (default is 0)
1166 // 0 => no calcul
1167 // 1 => calcul before all DSP procedures.
1168 // 2 => calcul after all DSP procedures.
1169 procedure InputSetLevelArrayEnable (InputIndex: cint32; levelcalc : cint32);
1170
1171 // InputIndex : InputIndex of existing input
1172 // result : left level from 0 to 1
1173 function InputGetLevelLeft (InputIndex: cint32): double;
1174
1175 // InputIndex : InputIndex of existing input
1176 // result : right level from 0 to 1
1177 function InputGetLevelRight (InputIndex: cint32): double;
1178
1179 // InputIndex : InputIndex of existing input
1180 // filterIndex : Filterindex of existing filter
1181 // result : list of left|right levels separed by $ character
1182 function InputFiltersGetLevelString (InputIndex: cint32): string;
1183
1184 // InputIndex : InputIndex of existing input
1185 // result : array of float of each filter.
1186 //in format levelfilter0left,levelfilter0right,levelfilter1left,levelfilter2right,...
1187 function InputFiltersGetLevelArray (InputIndex: cint32): TDArFloat;
1188
1189{$IF DEFINED (soundtouch)}
1190 // InputIndex : InputIndex of existing input
1191 // result : left level from 0 to 1
1192 function InputGetBPM (InputIndex: cint32): CDouble;
1193{$endif}
1194
1195 function InputUpdateTag (InputIndex: cint32): boolean;
1196{$IF DEFINED (webstream) and DEFINED (mpg123)}
1197 function InputUpdateICY (InputIndex: cint32; Var icy_data : pchar): integer;
1198{$endif}
1199
1200{$IF DEFINED (webstream)}
1201 // Type of audio of url stream, 0:mp3, 1:opus, 2:acc, -1:error
1202 function InputGetURLAudioType(InputIndex: cint32): integer;
1203 function InputGetURLContentType(InputIndex: cint32): string;
1204 function InputGetURLiceAudioInfo(InputIndex: cint32): string;
1205 function InputGetURLicyDescription(InputIndex: cint32): string;
1206 function InputGetURLicyGenre(InputIndex: cint32): string;
1207 function InputGetURLicyName(InputIndex: cint32): string;
1208 function InputGetURLicyUrl(InputIndex: cint32): string;
1209{$endif}
1210
1211 // Tag infos
1212 function InputGetTagTitle (InputIndex: cint32): pchar;
1213 function InputGetTagArtist (InputIndex: cint32): pchar;
1214 function InputGetTagAlbum (InputIndex: cint32): pchar;
1215 function InputGetTagDate (InputIndex: cint32): pchar;
1216 function InputGetTagComment (InputIndex: cint32): pchar;
1217 function InputGetTagTrack (InputIndex: cint32): pchar;
1218 function InputGetTagGenre (InputIndex: cint32): pchar;
1219 function InputGetTagTag (InputIndex: cint32): pchar;
1220
1221 // add a DSP procedure for input
1222 // InputIndex d: Input Index of an existing input
1223 // BeforeFunc : function to do before the buffer is filled
1224 // AfterFunc : function to do after the buffer is filled
1225 // EndedFunc : function to do after thread is finish
1226 // LoopProc : external procedure of object to synchronize after the buffer is filled
1227 // result : index of DSPin in array (DSPinIndex)
1228 // example : DSPinIndex1 := InputAddDSP (InputIndex1,@beforereverse,@afterreverse,nil);
1229 function InputAddDSP (InputIndex: cint32; BeforeFunc: TFunc;
1230 AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc ): cint32;
1231
1232 // InputIndex : Input Index of an existing input
1233 // DSPIndexIn : DSP Index of an existing DSP In
1234 // Enable : DSP enabled
1235 // example : InputSetDSP (InputIndex1,DSPinIndex1,True);
1236 procedure InputSetDSP (InputIndex: cint32; DSPinIndex: cint32; Enable: boolean);
1237
1238 // set enable true or false
1239 procedure OutputSetEnable (OutputIndex: cint32; enabled: boolean);
1240
1241 // useful if multi output
1242 // OutputIndex : OutputIndex of an existing Output
1243 // BeforeFunc : function to do before the buffer is filled
1244 // AfterFunc : function to do after the buffer is filled just before to give to output
1245 // EndedFunc : function to do after thread is finish
1246 // LoopProc : external procedure of object to synchronize after the buffer is filled
1247 // result : index of DSPout in array
1248 // example :DSPoutIndex1 := OutputAddDSP (OutputIndex1,@volumeproc,nil,nil);
1249 function OutputAddDSP (OutputIndex: cint32; BeforeFunc: TFunc;
1250 AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc): cint32;
1251
1252 // set level calculation (default is 0)
1253 // 0 => no calcul
1254 // 1 => calcul before all DSP procedures.
1255 // 2 => calcul after all DSP procedures.
1256 // 3 => calcul before and after all DSP procedures.
1257 procedure OutputSetLevelEnable (OutputIndex: cint32; levelcalc : cint32);
1258
1259 // OutputIndex : OutputIndex of existing Output
1260 // result : left level from 0 to 1
1261 function OutputGetLevelLeft (OutputIndex: cint32): double;
1262
1263 // OutputIndex : OutputIndex of existing Output
1264 // result : right level from 0 to 1
1265 function OutputGetLevelRight (OutputIndex: cint32): double;
1266
1267 // OutputIndex : OutputIndex of an existing Output
1268 // DSPoutIndex : DSPoutIndex of existing DSPout
1269 // Enable : DSP enabled
1270 // example : OutPutSetDSP (OutputIndex1,DSPoutIndex1,True);
1271 procedure OutPutSetDSP (OutputIndex: cint32; DSPoutIndex: cint32; Enable: boolean);
1272
1273 // InputIndex : InputIndex of an existing Input
1274 // TypeFilterL: Type of filter left:
1275 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1276 // fBandPass = 3, fLowPass = 4, fHighPass = 5)
1277 // LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
1278 // HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
1279 // GainL : gain left to apply to filter
1280 // TypeFilterR: Type of filter right (ignored if mono):
1281 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1282 // LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
1283 // HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
1284 // GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
1285 // AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
1286 // LoopProc : external procedure of object to synchronize after DSP done
1287 // result : index of DSPIn in array
1288 function InputAddFilter (InputIndex: cint32;
1289 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat;
1290 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat;
1291 AlsoBuf: boolean; LoopProc: TProc): cint32;
1292
1293 // InputIndex : InputIndex of an existing Input
1294 // DSPInIndex : DSPInIndex of existing DSPIn
1295 // TypeFilterL: Type of filter left:
1296 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1297 // fBandPass = 3, fLowPass = 4, fHighPass = 5)
1298 // LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
1299 // HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
1300 // GainL : gain left to apply to filter
1301 // TypeFilterR: Type of filter right (ignored if mono):
1302 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1303 // LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
1304 // HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
1305 // GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
1306 // AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
1307 // LoopProc : external procedure of object to synchronize after DSP done
1308 // Enable : Filter enabled
1309 procedure InputSetFilter (InputIndex: cint32; FilterIndex: cint32;
1310 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat;
1311 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat;
1312 AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
1313
1314 // Output : InputIndex of an existing Output
1315 // TypeFilterL: Type of filter left:
1316 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1317 // fBandPass = 3, fLowPass = 4, fHighPass = 5)
1318 // LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
1319 // HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
1320 // GainL : gain left to apply to filter
1321 // TypeFilterR: Type of filter right (ignored if mono):
1322 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1323 // LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
1324 // HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
1325 // GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
1326 // AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
1327 // LoopProc : external procedure of object to synchronize after DSP done
1328 // result : index of DSPIn in array
1329 function OutputAddFilter (OutputIndex: cint32;
1330 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat;
1331 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat;
1332 AlsoBuf: boolean; LoopProc: TProc): cint32;
1333
1334 // OuputIndex : InputIndex of an existing Output
1335 // DSPInIndex : DSPInIndex of existing DSPIn
1336 // TypeFilterL: Type of filter left:
1337 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1338 // fBandPass = 3, fLowPass = 4, fHighPass = 5)
1339 // LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
1340 // HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
1341 // GainL : gain left to apply to filter
1342 // TypeFilterR: Type of filter right (ignored if mono):
1343 // ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
1344 // LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
1345 // HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
1346 // GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
1347 // AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
1348 // LoopProc : external procedure of object to synchronize after DSP done
1349 // Enable : Filter enabled
1350 procedure OutputSetFilter (OutputIndex: cint32; FilterIndex: cint32;
1351 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat
1352 ;
1353 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat
1354 ;
1355 AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
1356
1357 // to get level of buffer (volume)
1358 function DSPLevel (Data: Tuos_Data): Tuos_Data;
1359
1360 function DSPLevelOut (Data: Tuos_Data): Tuos_Data;
1361
1362 // Convert mono 1 channel input to stereo 2 channels input.
1363 // Works only if the input is mono 1 channel othewise stereo 2 chan is keeped.
1364 // InputIndex : InputIndex of an existing Input
1365 // result : index of DSPIn in array
1366 // example DSPIndex1 := InputAddDSP1ChanTo2Chan (InputIndex1);
1367 function InputAddDSP1ChanTo2Chan (InputIndex: cint32): cint32;
1368
1369 // DSP Volume changer
1370 // InputIndex : InputIndex of an existing Input
1371 // VolLeft : Left volume
1372 // VolRight : Right volume
1373 // result : index of DSPIn in array
1374 // example DSPIndex1 := InputAddDSPVolume (InputIndex1,1,1);
1375 function InputAddDSPVolume (InputIndex: cint32; VolLeft: double;
1376 VolRight: double): cint32;
1377
1378 // DSP Volume changer
1379 // OutputIndex : OutputIndex of an existing Output
1380 // VolLeft : Left volume
1381 // VolRight : Right volume
1382 // result : otherwise index of DSPIn in array
1383 // example DSPIndex1 := OutputAddDSPVolume (InputIndex1,1,1);
1384 function OutputAddDSPVolume (OutputIndex: cint32; VolLeft: double;
1385 VolRight: double): cint32;
1386
1387{$IF DEFINED (noiseremoval)}
1388 // DSP Noise Removal
1389 // InputIndex : InputIndex of an existing Input
1390 // result : otherwise index of DSPIn in array
1391 // example DSPIndex1 := InputAddDSPNoiseRemoval (InputIndex1);
1392 function InputAddDSPNoiseRemoval (InputIndex: cint32): cint32;
1393
1394 procedure InputSetDSPNoiseRemoval (InputIndex: cint32; Enable: boolean);
1395
1396 // DSP Noise Removal
1397 // InputIndex : OutputIndex of an existing Output
1398 // result : otherwise index of DSPOut in array
1399 // example DSPIndex1 := OutputAddDSPNoiseRemoval (OutputIndex1);
1400 function OutputAddDSPNoiseRemoval (OutputIndex: cint32): cint32;
1401
1402 procedure OutputSetDSPNoiseRemoval (OutputIndex: cint32; Enable: boolean);
1403{$endif}
1404
1405 // InputIndex : InputIndex of an existing Input
1406 // DSPIndex : DSPIndex of an existing DSP
1407 // VolLeft : Left volume
1408 // VolRight : Right volume
1409 // Enable : Enabled
1410 // example InputSetDSPVolume (InputIndex1,DSPIndex1,1,0.8,True);
1411 procedure InputSetDSPVolume (InputIndex: cint32; DSPVolIndex: cint32;
1412 VolLeft: double; VolRight: double; Enable: boolean);
1413
1414 // OutputIndex : OutputIndex of an existing Output
1415 // DSPIndex : DSPIndex of an existing DSP
1416 // VolLeft : Left volume
1417 // VolRight : Right volume
1418 // Enable : Enabled
1419 // example OutputSetDSPVolume (InputIndex1,DSPIndex1,1,0.8,True);
1420 procedure OutputSetDSPVolume (OutputIndex: cint32; DSPVolIndex: cint32;
1421 VolLeft: double; VolRight: double; Enable: boolean);
1422 end;
1423
1424 // General public procedure/function (accessible for library uos too)
1425
1426function uos_GetInfoLibraries () : Pansichar;
1427
1428 {$IF DEFINED (portaudio)}
1429
1430procedure uos_UpdateDevice ();
1431
1432procedure uos_GetInfoDevice ();
1433
1434function uos_GetInfoDeviceStr () : Pansichar;
1435 {$endif}
1436
1437// load libraries... if libraryfilename = '' => do not load it... You may load what and when you want...
1438// PortAudio => needed for dealing with audio-device
1439// SndFile => needed for dealing with ogg, vorbis, flac and wav audio-files
1440// Mpg123 => needed for dealing with mp* audio-files
1441// Mp4ff and Faad => needed for dealing with acc, m4a audio-files
1442// opusfile => needed for dealing with opus audio-files
1443// XMP => needed for dealing with MOD audio-files
1444// Fdkaac => needed for webstreaming of aac files.
1445// If you want to load libraries from system, replace it by "'system'"
1446// If some libraries are not needed, replace it by "nil",
1447// for example : uos_loadlib ('system', SndFileFileName, 'system', nil, nil, nil, OpusFileFileName, nil, nil)
1448function uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
1449 FaadFileName
1450 , opusfileFileName, XMPFileName, fdkaacFilename : PChar) : cint32;
1451
1452// The same but without fdkaac. (for compatibility with previous version)
1453function uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
1454 FaadFileName
1455 , opusfileFileName, XMPFileName : PChar) : cint32;
1456
1457// The same but without libxmp and fdkaac. (for compatibility with previous version)
1458function uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
1459 FaadFileName
1460 , opusfileFileName : PChar) : cint32;
1461
1462// Unload all libraries... Do not forget to call it before close application...
1463procedure uos_unloadlib ();
1464
1465{$IF DEFINED (webstream)}
1466{ Function to check URL status with detailed error codes }
1467{ Returns:
1468 0: URL is accessible
1469 1: Invalid URL format
1470 2: Connection timeout or network error
1471 3: Server error (e.g., 404, 500)
1472 4: Redirect not followed
1473 5: Other network error}
1474function uos_CheckURLStatus(const URL: string): Integer;
1475{$endif}
1476
1477{$IF DEFINED (shout)}
1478// Shout => needed for dealing with IceCast server
1479// Opus => needed for dealing with encoding opus stream
1480function uos_LoadServerLib (ShoutFileName, OpusFileName : PChar) : cint32;
1481
1482// Unload server libraries... Do not forget to call it before close application...
1483procedure uos_unloadServerLib ();
1484{$endif}
1485
1486// Custom Unload libraries... if true, then unload the library. You may unload what and when you want...
1487procedure uos_unloadlibCust (PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
1488
1489// load plugin...
1490function uos_loadPlugin (PluginName, PluginFilename: PChar) : cint32;
1491
1492{$IF DEFINED (soundtouch)}
1493// From SoundTouch plugin
1494function uos_GetBPM (TheBuffer: TDArFloat; Channels: cint32; SampleRate: CDouble) : CDouble;
1495{$endif}
1496
1497// Unload Plugin...
1498procedure uos_unloadPlugin (PluginName: PChar);
1499
1500// To call at end of application.
1501// If uos_flat.pas was used, it will free all the uos_player created.
1502procedure uos_Free ();
1503
1504// version of uos
1505function uos_GetVersion () : cint32;
1506
1507// Create a memory buffer of an audio file.
1508// FileName : filename of audio file
1509// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
1510// bufferinfos : the infos of the buffer.
1511// frompos : from position (default: -1 = from begining, otherwise position in song)
1512// numbuf : number of frames to add to outmemory (default: -1 = all, otherwise number max of frames)
1513// result : The memory buffer
1514// example : buffmem := uos_File2buffer (edit5.Text,0,buffmem, buffinfos, -1, -1);
1515function uos_File2Buffer (Filename: Pchar; SampleFormat: cint32; Var bufferinfos: Tuos_BufferInfos;
1516 frompos : cint; numbuf : cint ): TDArFloat;
1517
1518// Create a memory buffer of an audio file.
1519// FileName : filename of audio file
1520// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
1521// Outmemory : the buffer to store data.
1522// bufferinfos : the infos of the buffer.
1523// frompos : from position (default: -1 = from begining, otherwise position in song)
1524// numbuf : number of buffer to add to outmemory (default: -1 = all, otherwise number max of buffers)
1525// result : The memory buffer
1526// example : buffmem := uos__Stream2Buffer (edit5.Text,0,buffmem, buffinfos, -1, -1);
1527function uos_Stream2Buffer (AudioFile: TMemoryStream; SampleFormat: int32; Var outmemory: TDArFloat;
1528 Var bufferinfos: Tuos_BufferInfos; frompos : cint; numbuf : cint): TDArFloat;
1529
1530// Create an audio file from an audio file.
1531// FileNameIN : filename of audio file IN (ogg, flac, wav, mp3, opus, aac,...)
1532// FileNameOUT : filename of audio file OUT (wav, pcm, custom)
1533// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
1534// typeout : Type of out file (-1:default=wav, 0:wav, 1:pcm, 2:custom)
1535// example : InputIndex1 := uos_File2File (edit5.Text,0,buffmem);
1536procedure uos_File2File (FilenameIN: Pchar; FilenameOUT: Pchar; SampleFormat: cint32; typeout: cint32 );
1537
1538// Create an audio wav file from a TMemoryStream.
1539// FileName : filename of wav saved file
1540// data : the memorystream
1541// BitsPerSample : 16 or 32 (bit)
1542// chan : number of channels
1543// samplerate : sample rate
1544procedure uos_MemStream2Wavfile (FileName: UTF8String; Data: TMemoryStream; BitsPerSample, chan:integer;
1545 samplerate : CDouble);
1546
1547// convert buffer int16 into float32.
1548function CvInt16ToFloat32 (Inbuf: TDArFloat): TDArFloat;
1549
1550// to initialize a custom bufferinfos: needed for AddFromMemoryBuffer () if no bufferinfos was created.
1551// all infos refer to the buffer used ---> length = length of the buffer div channels.
1552procedure uos_CustBufferInfos (Var bufferinfos: Tuos_BufferInfos; SampleRate: CDouble; SampleFormat
1553 : cint32; Channels: cint32; Length: cint32);
1554
1555// test a library to check if it can be loaded;
1556function uos_TestLoadLibrary (Filename: Pchar): boolean;
1557
1558const
1559 // error
1560 noError = 0;
1561 FilePAError = 10;
1562 LoadPAError = 11;
1563 FileSFError = 20;
1564 LoadSFError = 21;
1565 FileMPError = 30;
1566 LoadMPError = 31;
1567 LoadOPError = 41;
1568 FileOPError = 50;
1569 // uos Audio
1570 Stereo = 2;
1571 Mono = 1;
1572
1573 {$IF DEFINED (android)}
1574 DefRate = 48000;
1575 {$else}
1576 DefRate = 44100;
1577 {$endif}
1578
1579 // Write wav file
1580 ReadError = 1;
1581 HeaderError = 2;
1582 DataError = 3;
1583 FileCorrupt = 4;
1584 IncorectFileFormat = 5;
1585 HeaderWriteError = 6;
1586 StreamError = 7;
1587 // FFT Filters
1588 fBandAll = 0;
1589 fBandSelect = 1;
1590 fBandReject = 2;
1591 fBandPass = 3;
1592 fLowPass = 4;
1593 fHighPass = 5;
1594
1595 {$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
1596 MSG_CUSTOM1 = FPGM_USER + 1;
1597 {$endif}
1598
1599var
1600 theinc : integer = 0;
1601 theincbpm : integer = 0;
1602 tempload : boolean = false;
1603 paversion : UTF8String = '';
1604 sfversion : UTF8String = '';
1605 mpversion : UTF8String = '';
1606 tempSamplerate : CDouble;
1607 tempSampleFormat, tempchan, tempratio, tempLibOpen, tempLength : cint32;
1608 tempoutmemory: TDArFloat;
1609 uosPlayers: array of Tuos_Player;
1610 uosPlayersStat : array of cint32;
1611 uosLevelArray : TDArIARFloat;
1612 uosDeviceInfos: array of Tuos_DeviceInfos;
1613 uosLoadResult: Tuos_LoadResult;
1614 uosDeviceCount: cint32 = 0;
1615 uosDefaultDeviceIn: cint32 = -1;
1616 uosDefaultDeviceOut: cint32 = -1;
1617 uosInit: Tuos_Init = nil;
1618 uosIsActif : boolean = true;
1619
1620 {$IF DEFINED (windows)}
1621 old8087cw: word;
1622 {$endif}
1623
1624 {$IF DEFINED (Java)}
1625 theclass : JClass;
1626 {$endif}
1627
1628implementation
1629
1630{$IF DEFINED (webstream)}
1631{ Function to check URL status with detailed error codes }
1632{ Returns:
1633 0: URL is accessible
1634 1: Invalid URL format
1635 2: Connection timeout or network error
1636 3: Server error (e.g., 404, 500)
1637 4: Redirect not followed
1638 5: Other network error}
1639function uos_CheckURLStatus(const URL: string): Integer;
1640begin
1641result := CheckURLStatus(URL);
1642end;
1643{$endif}
1644
1645function uos_TestLoadLibrary (Filename: Pchar): boolean;
1646// test a library to check if it can be loaded;
1647var
1648 test_Handle: TLibHandle = NilHandle;
1649begin
1650 result := false;
1651 test_Handle := DynLibs.SafeLoadLibrary (Filename);
1652 if test_Handle <> DynLibs.NilHandle then
1653 begin
1654 DynLibs.UnloadLibrary (test_Handle);
1655 test_Handle := DynLibs.NilHandle;
1656 result := true;
1657 end;
1658end;
1659
1660procedure TDummyThread.Execute;
1661begin
1662 FreeOnTerminate := True;
1663 Terminate;
1664end;
1665
1666function RoundMath (aV:double): int64;
1667overload;
1668begin
1669 if aV>=0 then
1670 result := Trunc (aV+0.5)
1671 else
1672 result := Trunc (aV-0.5);
1673end;
1674
1675function RoundMath (aV:single): int64;
1676overload;
1677begin
1678 if aV>=0 then
1679 result := Trunc (aV+0.5)
1680 else
1681 result := Trunc (aV-0.5);
1682end;
1683
1684function FormatBuf (Inbuf: TDArFloat; format: cint32): TDArFloat;
1685var
1686 x: cint32;
1687 ps: PDArShort;
1688 // if input is Int16 format
1689 pl: PDArLong;
1690 // if input is Int32 format
1691 pf: PDArFloat;
1692 // if input is Float32 format
1693begin
1694
1695 case format of
1696 2:
1697 begin
1698 ps := @inbuf;
1699 for x := 0 to high (inbuf) do
1700 ps^[x] := cint16 (trunc (ps^[x]));
1701 end;
1702 1:
1703 begin
1704 pl := @inbuf;
1705 for x := 0 to high (inbuf) do
1706 pl^[x] := cint32 (trunc (pl^[x]));
1707 end;
1708 0:
1709 begin
1710 pf := @inbuf;
1711 for x := 0 to high (inbuf) do
1712 pf^[x] := cfloat (pf^[x]);
1713 end;
1714 end;
1715 Result := Inbuf;
1716end;
1717
1718function CvFloat32ToInt16 (Inbuf: TDArFloat): TDArShort;
1719var
1720 x, i: cint32;
1721 arsh: TDArShort;
1722begin
1723 SetLength (arsh, length (inbuf));
1724 for x := 0 to high (Inbuf) do
1725 begin
1726 i := trunc (Inbuf[x] * 32768);
1727 if i > 32767 then
1728 i := 32767
1729 else
1730 if i < -32768 then
1731 i := -32768;
1732 arsh[x] := i;
1733 end;
1734 Result := arsh;
1735end;
1736
1737function CvFloat32ToInt32 (Inbuf: TDArFloat): TDArLong;
1738var
1739 i: int64;
1740 x : cint32;
1741 arlo: TDArLong;
1742begin
1743 SetLength (arlo, length (inbuf));
1744 for x := 0 to high (Inbuf) do
1745 begin
1746 i := trunc (Inbuf[x] * 2147483647);
1747 if i > 2147483647 then
1748 i := 2147483647
1749 else
1750 if i < -2147483648 then
1751 i := -2147483648;
1752 arlo[x] := i;
1753 end;
1754 Result := arlo;
1755end;
1756
1757function CvFloat32ToInt32fl (Inbuf: TDArFloat; nb:integer): TDArFloat;
1758var
1759 x : cint32;
1760 pl2: PDArLong;
1761 // if input is Int32 format
1762 pf: PDArfloat;
1763 buffer2 : TDArFloat;
1764
1765begin
1766 pf := @Inbuf;
1767 pl2 := @Buffer2;
1768
1769 setlength (buffer2,nb);
1770
1771 for x := 0 to nb -1 do
1772 begin
1773 pl2^[x] := trunc ((pf^[x]) * 2147483647);
1774 end;
1775 Result := buffer2;
1776end;
1777
1778function CvInt16ToFloat32 (Inbuf: TDArFloat): TDArFloat;
1779var
1780 x: cint32;
1781 arfl: TDArFloat;
1782 ps: PDArShort;
1783begin
1784 setlength (arfl,length (Inbuf));
1785 ps := @inbuf;
1786 for x := 0 to high (Inbuf) do
1787 arfl[x] := ps^[x] / 32768;
1788 Result := arfl;
1789end;
1790
1791function CvMonoToStereo (Inbuf: TDArFloat; len : cint32): TDArFloat;
1792var
1793 x, y: cint32;
1794 arsh: TDArFloat;
1795begin
1796
1797 if len > 0 then
1798 begin
1799 setlength (arsh, len * 2);
1800
1801 x := 0;
1802 y := 0;
1803
1804 while x < (len )-1 do
1805 begin
1806 arsh[y] := Inbuf[x];
1807 inc (y);
1808 arsh[y] := Inbuf[x];
1809 inc (y);
1810 inc (x);
1811 end;
1812
1813 Result := arsh;
1814 end
1815 else Result := Inbuf;
1816end;
1817
1818
1819function CvStereoToMono (Inbuf: TDArFloat; len : cint32): TDArFloat;
1820var
1821 x, y: cint32;
1822 arsh: TDArFloat;
1823begin
1824
1825 if len > 0 then
1826 begin
1827 setlength (arsh, len);
1828
1829 x := 0;
1830 y := 0;
1831
1832 while x < (len * 2)-1 do
1833 begin
1834 // TODO -> this takes only chan1, not (chan1+chan2)/2 -> it get bad noise dont know why ???...
1835 // arsh[y] := trunc ((Inbuf[x] + Inbuf[x+1])/ 2);
1836
1837 arsh[y] := Inbuf[x+1];
1838
1839 inc (y);
1840 x := x + 2;
1841 end;
1842
1843 Result := arsh;
1844 end
1845 else Result := Inbuf;
1846end;
1847
1848function CvInt32ToFloat32 (Inbuf: TDArFloat): TDArFloat;
1849var
1850 x: cint32;
1851 arfl: TDArFloat;
1852 pl: PDArLong;
1853begin
1854 setlength (arfl,length (Inbuf));
1855 pl := @inbuf;
1856 for x := 0 to high (Inbuf) do
1857 arfl[x] := pl^[x] / 2147483647;
1858 Result := arfl;
1859end;
1860
1861// convert a Tmemory stream into a wav file.
1862procedure uos_MemStream2Wavfile (FileName: UTF8String; Data: TMemoryStream; BitsPerSample, chan:
1863 integer;
1864 samplerate : CDouble);
1865var
1866 f: TFileStream;
1867 wFileSize: LongInt;
1868 wChunkSize: LongInt;
1869 ID: array[0..3] of char;
1870 Header: Tuos_WaveHeaderChunk;
1871begin
1872 f := Nil;
1873 f := TFileStream.Create (FileName, fmCreate);
1874 f.Seek (0, soFromBeginning);
1875 try
1876 ID := 'RIFF';
1877 f.WriteBuffer (ID, 4);
1878 wFileSize := 0;
1879 f.WriteBuffer (wFileSize, 4);
1880 ID := 'WAVE';
1881 f.WriteBuffer (ID, 4);
1882 ID := 'fmt ';
1883 f.WriteBuffer (ID, 4);
1884 wChunkSize := SizeOf (Header);
1885 f.WriteBuffer (wChunkSize, 4);
1886
1887 Header.wFormatTag := 1;
1888 Header.wChannels := chan;
1889 Header.wSamplesPerSec := roundmath (samplerate);
1890 Header.wBitsPerSample := BitsPerSample;
1891 Header.wBlockAlign := chan * (BitsPerSample Div 8);
1892 Header.wAvgBytesPerSec := roundmath (samplerate) * Header.wBlockAlign;
1893 Header.wcbSize := 0;
1894
1895 f.WriteBuffer (Header, SizeOf (Header));
1896 except
1897
1898end;
1899try
1900 ID := 'data';
1901 f.WriteBuffer (ID, 4);
1902 wChunkSize := Data.Size;
1903 f.WriteBuffer (wChunkSize, 4);
1904except
1905end;
1906
1907Data.Seek (0, soFromBeginning);
1908f.CopyFrom (Data, Data.Size);
1909f.Seek (SizeOf (ID), soFromBeginning);
1910wFileSize := f.Size - SizeOf (ID) - SizeOf (wFileSize);
1911f.write (wFileSize, 4);
1912f.Free;
1913end;
1914
1915function WriteWaveFromMem (FileName: UTF8String; Data: Tuos_FileBuffer): word;
1916var
1917 f: TFileStream;
1918 wFileSize: LongInt;
1919 wChunkSize: LongInt;
1920 ID: array[0..3] of char;
1921 Header: Tuos_WaveHeaderChunk;
1922begin
1923 Result := noError;
1924 f := Nil;
1925 f := TFileStream.Create (FileName, fmCreate);
1926 f.Seek (0, soFromBeginning);
1927 if Data.FileFormat = 0 then
1928 begin
1929 // wav file
1930 try
1931 ID := 'RIFF';
1932 f.WriteBuffer (ID, 4);
1933 wFileSize := 0;
1934 f.WriteBuffer (wFileSize, 4);
1935 ID := 'WAVE';
1936 f.WriteBuffer (ID, 4);
1937 ID := 'fmt ';
1938 f.WriteBuffer (ID, 4);
1939 wChunkSize := SizeOf (Header);
1940 f.WriteBuffer (wChunkSize, 4);
1941
1942 Header.wFormatTag := 1;
1943 Header.wChannels := Data.wChannels;
1944 Header.wSamplesPerSec := Data.wSamplesPerSec;
1945 Header.wBlockAlign := Data.wChannels * (Data.wBitsPerSample Div 8);
1946 Header.wAvgBytesPerSec := Data.wSamplesPerSec * Header.wBlockAlign;
1947 Header.wBitsPerSample := Data.wBitsPerSample;
1948 Header.wcbSize := 0;
1949
1950 f.WriteBuffer (Header, SizeOf (Header));
1951 except
1952 Result := HeaderWriteError;
1953 end;
1954 try
1955 ID := 'data';
1956 f.WriteBuffer (ID, 4);
1957 wChunkSize := Data.DataMS.Size;
1958 f.WriteBuffer (wChunkSize, 4);
1959 except
1960 Result := StreamError;
1961end;
1962
1963end;
1964
1965Data.DataMS.Seek (0, soFromBeginning);
1966f.CopyFrom (Data.DataMS, Data.DataMS.Size);
1967f.Seek (SizeOf (ID), soFromBeginning);
1968wFileSize := f.Size - SizeOf (ID) - SizeOf (wFileSize);
1969f.write (wFileSize, 4);
1970f.Free;
1971end;
1972
1973
1974procedure WriteWave (FileName: UTF8String; Data: Tuos_FileBuffer);
1975var
1976 wFileSize: cuint32;
1977 wDataSize: cuint32;
1978begin
1979 Data.data.Position := 4;
1980 // after 'RIFF'
1981 wFileSize := Data.data.Size - 8;
1982 // amount of bytes following 'RIFF' and ckSize
1983 Data.data.write (wFileSize, 4);
1984
1985 Data.data.Position := 42;
1986 // after 'DATA'
1987 wDataSize := Data.data.Size - 46;
1988 // 46 bytes is the size of the complete header
1989 Data.data.write (wDataSize, 4);
1990
1991 Data.data.Free;
1992end;
1993
1994{$IF DEFINED (sndfile) or DEFINED (mpg123)}
1995function mpg_read_stream (ahandle: Pointer; AData: Pointer; ACount: Integer): Integer;
1996cdecl;
1997var
1998 Stream: TStream absolute ahandle;
1999begin
2000 Result := Stream.Read (AData^, ACount);
2001end;
2002
2003function mpg_seek_stream (ahandle: Pointer; offset: Integer;
2004 whence: Integer): Integer;
2005cdecl;
2006var
2007 Stream: TStream absolute ahandle;
2008begin
2009 try
2010 case whence of
2011 SEEK_SET : Result := Stream.Seek (offset, soFromBeginning);
2012 SEEK_CUR : Result := Stream.Seek (offset, soFromCurrent);
2013 SEEK_END : Result := Stream.Seek (offset, soFromEnd);
2014 else
2015 Result := 0;
2016 end;
2017 except
2018 Result := 0;
2019end;
2020end;
2021
2022procedure mpg_close_stream (ahandle: Pointer);
2023// not used, uos does it...
2024begin
2025 TObject (ahandle).Free;
2026end;
2027{$endif}
2028
2029{$IF DEFINED (webstream)}
2030// should use this for pipes vs memorystream ?
2031function mpg_seek_url (ahandle: Pointer; aoffset: Integer): Integer;
2032cdecl;
2033var
2034 Stream: TStream absolute ahandle;
2035begin
2036 // pipe streams are not seekable but memory and filestreams are
2037 Result := 0;
2038 try
2039 if aoffset > 0 then
2040 Result := Stream.Seek (aoffset, soFromCurrent);
2041 except
2042 Result := 0;
2043end;
2044end;
2045{$endif}
2046
2047// Add an input from audio file with custom parameters
2048// FileName : filename of audio file
2049// OutputIndex : Output index of used output
2050// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
2051// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
2052// FramesCount : default: -1 (4096)
2053// Outmemory : the buffer to store data.
2054// bufferinfos : the infos of the buffer
2055// frompos : from position (default: -1 = from begining, otherwise position in song)
2056// numbuf : number of buffer to add to outmemory (default: -1 = all, otherwise number max of buffers)
2057// result : Input Index in array -1 = error
2058// example : InputIndex1 := Filetobuffer (edit5.Text,-1,0,-1, buffmem, buffinfos, -1);
2059function Filetobuffer (Filename: Pchar; OutputIndex: cint32;
2060 SampleFormat: cint32; FramesCount: cint32; Var outmemory: TDArFloat;
2061 Var bufferinfos: Tuos_BufferInfos; frompos: cint; numbuf : cint ): TDArFloat;
2062var
2063 theplayer : Tuos_Player;
2064 in1 : cint32;
2065begin
2066 theplayer := Tuos_Player.Create ();
2067
2068 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2069 writeln ('begin Filetobuffer');
2070 {$endif}
2071
2072 In1 := theplayer.AddFromFile ( pchar (Filename), OutputIndex, SampleFormat, FramesCount);
2073 if in1 > -1 then
2074 begin
2075
2076 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2077 writeln ('in1 = ' + inttostr (in1));
2078 writeln ('theplayer.InputLength (In1) = ' + inttostr (theplayer.InputLength (In1)));
2079 {$endif}
2080
2081 SetLength (outmemory, 0);
2082
2083 tempchan := theplayer.StreamIn[in1].Data.Channels;
2084 tempratio := theplayer.StreamIn[in1].Data.ratio;
2085 tempSampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
2086 tempSamplerate := theplayer.StreamIn[in1].Data.Samplerate;
2087 templength := theplayer.StreamIn[in1].Data.Length;
2088 bufferinfos.SampleRate := theplayer.StreamIn[in1].Data.Samplerate;
2089 bufferinfos.SampleRateRoot := theplayer.StreamIn[in1].Data.Samplerate;
2090 bufferinfos.SampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
2091 bufferinfos.Channels := theplayer.StreamIn[in1].Data.Channels;
2092 bufferinfos.Filename := theplayer.StreamIn[in1].Data.Filename;
2093 bufferinfos.Title := theplayer.StreamIn[in1].Data.Title;
2094 bufferinfos.Copyright := theplayer.StreamIn[in1].Data.Copyright;
2095 bufferinfos.Software := theplayer.StreamIn[in1].Data.Software;
2096 bufferinfos.Artist := theplayer.StreamIn[in1].Data.Artist;
2097 bufferinfos.Comment := theplayer.StreamIn[in1].Data.Comment;
2098 bufferinfos.Date := theplayer.StreamIn[in1].Data.Date;
2099 bufferinfos.Tag := theplayer.StreamIn[in1].Data.Tag;
2100 bufferinfos.Album := theplayer.StreamIn[in1].Data.Album;
2101 bufferinfos.Genre := theplayer.StreamIn[in1].Data.Genre;
2102 bufferinfos.Track := theplayer.StreamIn[in1].Data.Track;
2103 bufferinfos.HDFormat := theplayer.StreamIn[in1].Data.HDFormat;
2104 bufferinfos.Sections := theplayer.StreamIn[in1].Data.Sections;
2105 bufferinfos.Encoding := theplayer.StreamIn[in1].Data.Encoding;
2106 bufferinfos.bitrate := theplayer.StreamIn[in1].Data.bitrate;
2107 bufferinfos.Length := theplayer.StreamIn[in1].Data.Length;
2108 bufferinfos.LibOpen := 0;
2109 bufferinfos.Ratio := 2;
2110
2111 theplayer.StreamIn[in1].Data.numbuf := numbuf;
2112
2113 theplayer.AddIntoMemoryBuffer ( @outmemory );
2114 theplayer.Play (0);
2115
2116 if frompos > 0 then theplayer.inputseek (in1,frompos);
2117
2118 while (theplayer.getstatus > 0) do
2119 sleep (100);
2120
2121 end;
2122
2123 {$IF DEFINED (mse)}
2124 theplayer.destroy;
2125 {$endif}
2126 result := outmemory;
2127end;
2128
2129 {$IF DEFINED (soundtouch)}
2130function uos_GetBPM (TheBuffer: TDArFloat; Channels: cint32; SampleRate: CDouble) : CDouble;
2131// From SoundTouch plugin
2132var
2133 BPMhandle : THandle;
2134 sr, ch : cint32;
2135begin
2136
2137 if SampleRate = -1 then sr := 44100
2138 else sr := roundmath (SampleRate);
2139 if Channels = -1 then ch := 2
2140 else ch := Channels;
2141
2142 BPMhandle := bpm_createInstance (ch,sr);
2143 bpm_putSamples (BPMhandle, pcfloat (thebuffer), length (thebuffer) div Channels);
2144
2145 result := bpm_getBpm (BPMhandle);
2146
2147 bpm_destroyInstance (BPMhandle);
2148
2149end;
2150 {$endif}
2151
2152// Create a memory buffer of an audio file.
2153// FileName : filename of audio file
2154// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
2155// bufferinfos : the infos of the buffer.
2156// frompos : from position (default: -1 = from begining, otherwise position in song)
2157// numbuf : number of frames to add to outmemory (default: -1 = all, otherwise number max of frames)
2158// result : The memory buffer
2159// example : buffmem := uos_File2buffer (edit5.Text,0,buffmem, buffinfos, -1, -1);
2160function uos_File2Buffer (Filename: Pchar; SampleFormat: cint32; Var bufferinfos: Tuos_BufferInfos;
2161 frompos : cint; numbuf : cint ): TDArFloat;
2162 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2163var
2164 i : integer;
2165 st : string;
2166 {$endif}
2167begin
2168
2169 result := Filetobuffer (Filename,-1, SampleFormat, 1024, result, bufferinfos, frompos, numbuf);
2170
2171 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2172 writeln ('After Filetobuffer');
2173 writeln ('length (result) =' +inttostr (length (result)));
2174 st := '';
2175 for i := 0 to length (result) -1 do
2176 st := st + '|' + inttostr (i) + '=' + floattostr (result[i]);
2177 WriteLn ('OUTPUT DATA into portaudio------------------------------');
2178 WriteLn (st);
2179 {$endif}
2180
2181end;
2182
2183// Add an input from audio file with custom parameters
2184// FileName : filename of audio file
2185// OutputIndex : Output index of used output
2186// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
2187// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
2188// FramesCount : default: -1 (4096)
2189// Outmemory : the buffer to store data.
2190// bufferinfos : the infos of the buffer
2191// frompos : from position (default: -1 = from begining, otherwise position in song)
2192// numbuf : number of buffer to add to outmemory (default: -1 = all, otherwise number max of buffers)
2193// result : Input Index in array -1 = error
2194// example : InputIndex1 := streamtobuffer (edit5.Text,-1,0,-1, buffmem, buffinfos, -1);
2195function Streamtobuffer (AudioFile:TMemoryStream; OutputIndex: cint32;SampleFormat: cint32;
2196 FramesCount: cint32;
2197 Var outmemory: TDArFloat; Var bufferinfos: Tuos_BufferInfos; frompos: cint;
2198 numbuf : cint): TDArFloat;
2199
2200var
2201 theplayer : Tuos_Player;
2202 in1 : cint32;
2203
2204begin
2205 theplayer := Tuos_Player.Create ();
2206 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2207 writeln ('begin Filetobuffer');
2208 {$endif}
2209
2210 //In1 := theplayer.AddFromFile ( pchar (Filename), OutputIndex, SampleFormat, FramesCount);
2211 In1 := theplayer.AddFromMemoryStream ( AudioFile,-1, OutputIndex, SampleFormat, FramesCount);
2212
2213 if in1 > -1 then
2214 begin
2215 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2216 writeln ('in1 = ' + inttostr (in1));
2217 writeln ('theplayer.InputLength (In1) = ' + inttostr (theplayer.InputLength (In1)));
2218 {$endif}
2219
2220 SetLength (outmemory, 0);
2221
2222 tempchan := theplayer.StreamIn[in1].Data.Channels;
2223 tempratio := theplayer.StreamIn[in1].Data.ratio;
2224 tempSampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
2225 tempSamplerate := theplayer.StreamIn[in1].Data.Samplerate;
2226 templength := theplayer.StreamIn[in1].Data.Length;
2227
2228 bufferinfos.SampleRate := theplayer.StreamIn[in1].Data.Samplerate;
2229 bufferinfos.SampleRateRoot := theplayer.StreamIn[in1].Data.Samplerate;
2230 bufferinfos.SampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
2231 bufferinfos.Channels := theplayer.StreamIn[in1].Data.Channels;
2232 bufferinfos.Filename := theplayer.StreamIn[in1].Data.Filename;
2233 bufferinfos.Title := theplayer.StreamIn[in1].Data.Title;
2234 bufferinfos.Copyright := theplayer.StreamIn[in1].Data.Copyright;
2235 bufferinfos.Software := theplayer.StreamIn[in1].Data.Software;
2236 bufferinfos.Artist := theplayer.StreamIn[in1].Data.Artist;
2237 bufferinfos.Comment := theplayer.StreamIn[in1].Data.Comment;
2238 bufferinfos.Date := theplayer.StreamIn[in1].Data.Date;
2239 bufferinfos.Tag := theplayer.StreamIn[in1].Data.Tag;
2240 bufferinfos.Album := theplayer.StreamIn[in1].Data.Album;
2241 bufferinfos.Track := theplayer.StreamIn[in1].Data.Track;
2242 bufferinfos.Genre := theplayer.StreamIn[in1].Data.Genre;
2243 bufferinfos.HDFormat := theplayer.StreamIn[in1].Data.HDFormat;
2244 bufferinfos.Sections := theplayer.StreamIn[in1].Data.Sections;
2245 bufferinfos.Encoding := theplayer.StreamIn[in1].Data.Encoding;
2246 bufferinfos.bitrate := theplayer.StreamIn[in1].Data.bitrate;
2247 bufferinfos.Length := theplayer.StreamIn[in1].Data.Length;
2248 bufferinfos.LibOpen := 0;
2249 bufferinfos.Ratio := 2;
2250
2251 theplayer.StreamIn[in1].Data.numbuf := numbuf;
2252
2253 theplayer.AddIntoMemoryBuffer ( @outmemory );
2254 theplayer.Play (0);
2255 if frompos > 0 then theplayer.inputseek (in1,frompos);
2256
2257 while (theplayer.getstatus > 0) do
2258 sleep (100);
2259
2260 end;
2261 {$IF DEFINED (mse)}
2262 theplayer.destroy;
2263 {$endif}
2264 result := outmemory;
2265end;
2266
2267// Create a memory buffer of an audio file.
2268// FileName : filename of audio file
2269// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
2270// Outmemory : the buffer to store data.
2271// bufferinfos : the infos of the buffer.
2272// frompos : from position (default: -1 = from begining, otherwise position in song)
2273// numbuf : number of buffer to add to outmemory (default: -1 = all, otherwise number max of buffers)
2274// result : The memory buffer
2275// example : buffmem := uos_File2buffer (edit5.Text,0,buffmem, buffinfos, -1);
2276function uos_Stream2Buffer (AudioFile: TMemoryStream; SampleFormat: int32;
2277 Var outmemory: TDArFloat; Var bufferinfos: Tuos_BufferInfos; frompos:
2278 cint; numbuf : cint): TDArFloat;
2279begin
2280 result := Streamtobuffer (AudioFile,-1, SampleFormat, -1, outmemory, bufferinfos, frompos, numbuf)
2281 ;
2282end;
2283
2284// Create an audio file from an audio file.
2285// FileNameIN : filename of audio file IN (ogg, flac, wav, mp3, opus, aac,...)
2286// FileNameOUT : filename of audio file OUT (wav, pcm, custom)
2287// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
2288// typeout : Type of out file (-1:default=wav, 0:wav, 1:pcm, 2:custom)
2289// example : InputIndex1 := uos_File2File (edit5.Text,0,buffmem);
2290procedure uos_File2File (FilenameIN: Pchar; FilenameOUT: Pchar; SampleFormat: cint32; typeout:
2291 cint32 );
2292var
2293 theplayer : Tuos_Player;
2294 in1 : cint32;
2295begin
2296
2297 theplayer := Tuos_Player.Create ();
2298
2299 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2300 writeln ('begin File2file');
2301 {$endif}
2302 In1 := theplayer.AddFromFile ( pchar (FilenameIN), -1, SampleFormat, -1);
2303 if in1 > -1 then
2304 begin
2305 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2306 writeln ('in1 = ' + inttostr (in1));
2307 writeln ('theplayer.InputLength (In1) = ' + inttostr (theplayer.InputLength (In1)));
2308 {$endif}
2309
2310 theplayer.AddIntoFile (FilenameOUT, theplayer.StreamIn[0].data.samplerate,
2311 theplayer.StreamIn[0].data.channels, SampleFormat, -1 , typeout);
2312
2313 theplayer.Play (0);
2314
2315 while (theplayer.getstatus > 0) do
2316 sleep (100);
2317 end;
2318 {$IF DEFINED (mse)}
2319 theplayer.destroy;
2320 {$endif}
2321end;
2322
2323 {$IF DEFINED (mse)}
2324 {$else}
2325constructor TuosThread.Create (CreateSuspended: boolean; AParent: TObject;
2326 Const StackSize: SizeUInt);
2327begin
2328 theparent := AParent;
2329 FreeOnTerminate := true;
2330 inherited Create (CreateSuspended, StackSize);
2331 Priority := tpTimeCritical;
2332end;
2333 {$endif}
2334
2335// Get the status of the player : -1 => error or not yet played, 0 => has stopped, 1 => is running, 2 => is paused.
2336function Tuos_Player.GetStatus () : cint32;
2337begin
2338 result := -1;
2339 if (isAssigned = True) then result := Status
2340 else result := -1;
2341end;
2342
2343function Tuos_Player.IsLooped: Boolean;
2344begin
2345 Result := (NLooped <> 0) And
2346 (NLooped <> 1);
2347end;
2348
2349procedure Tuos_Player.PlayEx (no_free: Boolean; nloop: Integer; paused: boolean= false);
2350var
2351 x: cint32;
2352begin
2353 if (isAssigned = True) and (not IsLooped) then
2354 begin
2355 NLooped := nloop;
2356 NoFree := no_free;
2357
2358 {$IF DEFINED (portaudio)}
2359 for x := 0 to high (StreamOut) do
2360 if StreamOut[x].Data.HandleSt <> nil then
2361 Pa_StartStream (StreamOut[x].Data.HandleSt);
2362 {$endif}
2363
2364 for x := 0 to high (StreamIn) do
2365 begin
2366 {$IF DEFINED (portaudio)}
2367 if (StreamIn[x].Data.HandleSt <> nil) and (StreamIn[x].Data.TypePut = 1) then
2368 Pa_StartStream (StreamIn[x].Data.HandleSt);
2369 {$endif}
2370
2371 if (no_free = true) and (StreamIn[x].Data.HandleSt <> nil)
2372 and (StreamIn[x].Data.TypePut = 4) then
2373 StreamIn[x].Data.posmem := 0;
2374
2375 if (no_free = true) and (StreamIn[x].Data.HandleSt <> nil)
2376 and ( (StreamIn[x].Data.TypePut = 0) or (StreamIn[x].Data.TypePut = 4)) then
2377 InputSeek (x, 0);
2378
2379 StreamIn[x].Data.status := 1;
2380
2381 end;
2382
2383 Status := 1;
2384
2385 if isGlobalPause = true then
2386 RTLeventSetEvent (uosInit.evGlobalPause)
2387 else
2388 RTLeventSetEvent (evPause);
2389
2390 if paused = true then
2391 begin
2392 if isGlobalPause = true then
2393 RTLeventReSetEvent (uosInit.evGlobalPause)
2394 else
2395 RTLeventResetEvent (evPause);
2396 end;
2397
2398 //protect from multiple instances of thread
2399 if thethread = nil then
2400 begin
2401 {$IF DEFINED (mse)}
2402 thethread := tmsethread.create (@execute);
2403 {$else}
2404 thethread := tuosthread.Create (false,self);
2405 {$endif}
2406 end;
2407 end;
2408end;
2409
2410// Start play paused with loop
2411procedure Tuos_Player.PlayPaused (nloop: Integer = 0);
2412begin
2413 PlayEx (False,nloop,true);
2414end;
2415
2416// Start play paused with loop and not free player at end
2417procedure Tuos_Player.PlayNoFreePaused (nloop: Integer = 0);
2418begin
2419 PlayEx (true,nloop,true);
2420end;
2421
2422procedure Tuos_Player.Play (nloop: Integer = 0);
2423begin
2424 PlayEx (False,nloop);
2425end;
2426
2427procedure Tuos_Player.PlayNoFree (nloop: Integer = 0);
2428begin
2429 PlayEx (True,nloop);
2430end;
2431
2432procedure Tuos_Player.FreePlayer ();
2433// Works only when PlayNoFree () was used: free the player
2434begin
2435 if isAssigned then
2436 begin
2437 NLooped := 0;
2438 NoFree := False;
2439 //if it has never been put into play (= there is no thread for free)..
2440 if thethread = nil then
2441 Play ();
2442 Stop;
2443 end;
2444end;
2445
2446// Resume Playing after Pause
2447procedure Tuos_Player.RePlay ();
2448begin
2449 if (Status > 0) and (isAssigned = True) then
2450 begin
2451 Status := 1;
2452 if isGlobalPause = true then
2453 RTLeventSetEvent (uosInit.evGlobalPause)
2454 else
2455 RTLeventSetEvent (evPause);
2456 end;
2457end;
2458
2459procedure Tuos_Player.Stop ();
2460begin
2461 //writeln (inttostr (Status));
2462 if (Status <> 0) and (isAssigned = True) then
2463 begin
2464 if status < 0 then playpaused;
2465 NLooped := 0;
2466 if isGlobalPause = true then
2467 RTLeventSetEvent (uosInit.evGlobalPause)
2468 else
2469 RTLeventSetEvent (evPause);
2470 Status := 0;
2471 end;
2472end;
2473
2474procedure Tuos_Player.Pause ();
2475begin
2476 if (Status > 0) and (isAssigned = True) then
2477 begin
2478 if isGlobalPause = true then
2479 RTLeventReSetEvent (uosInit.evGlobalPause)
2480 else
2481 RTLeventResetEvent (evPause);
2482 Status := 2;
2483 end;
2484end;
2485
2486procedure Tuos_Player.InputSeek (InputIndex:cint32; pos: Tcount_t);
2487// change position in samples
2488begin
2489 if (isAssigned = True) then StreamIn[InputIndex].Data.Poseek := pos;
2490end;
2491
2492procedure Tuos_Player.InputSeekSeconds (InputIndex: cint32; pos: cfloat);
2493// change position in seconds
2494begin
2495 if (isAssigned = True) then StreamIn[InputIndex].Data.Poseek :=
2496 trunc (pos * StreamIn[InputIndex]
2497 .Data.SampleRate);
2498end;
2499
2500procedure Tuos_Player.InputSeekTime (InputIndex: cint32; pos: TTime);
2501// change position in time format
2502var
2503 ho, mi, se, ms: word;
2504 possample : cint32;
2505begin
2506 if (isAssigned = True) then
2507 begin
2508 sysutils.DecodeTime (pos, ho, mi, se, ms);
2509
2510 possample := trunc (( (ho * 3600) + (mi * 60) + se + (ms / 1000)) *
2511 StreamIn[InputIndex].Data.SampleRate);
2512
2513 StreamIn[InputIndex].Data.Poseek := possample;
2514
2515 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2516 WriteLn ('TTime: '+ timetostr (pos));
2517 WriteLn ('SeekTime () : Data.Poseek: '+ inttostr (possample));
2518 {$endif}
2519 end;
2520end;
2521
2522procedure Tuos_Player.InputSetEnable (InputIndex: cint32; enabled: boolean);
2523// set enable true or false
2524begin
2525 StreamIn[InputIndex].data.Enabled := enabled;
2526end;
2527
2528function Tuos_Player.InputLength (InputIndex: cint32): cint32;
2529// gives length in samples
2530begin
2531 result := 0;
2532 if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Length;
2533end;
2534
2535function Tuos_Player.InputLengthSeconds (InputIndex: cint32): cfloat;
2536begin
2537 result := 0;
2538 if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Length / StreamIn[InputIndex].
2539 Data.SampleRate;
2540end;
2541
2542function Tuos_Player.InputLengthTime (InputIndex: cint32): TTime;
2543var
2544 tmp: cfloat;
2545 h, m, s, ms: word;
2546begin
2547 Result := sysutils.EncodeTime (0, 0, 0, 0);
2548 if (isAssigned = True) then tmp := InputLengthSeconds (InputIndex);
2549 ms := trunc (frac (tmp) * 1000);
2550 h := trunc (tmp / 3600);
2551 m := trunc (tmp / 60 - h * 60);
2552 s := trunc (tmp - (h * 3600 + m * 60));
2553 Result := sysutils.EncodeTime (h, m, s, ms);
2554end;
2555
2556function Tuos_Player.InputPosition (InputIndex: cint32): cint32;
2557// gives current position
2558begin
2559 Result := 0;
2560 if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Position;
2561end;
2562
2563procedure Tuos_Player.InputSetFrameCount (InputIndex: cint32; framecount : cint32);
2564begin
2565 if (isAssigned = True) then
2566
2567 case StreamIn[InputIndex].Data.LibOpen of
2568 0:
2569 StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels);
2570
2571 1:
2572 StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels)*
2573 2 ;
2574
2575 2:
2576 StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels);
2577
2578 3:
2579 StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels);
2580
2581 4:
2582 StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels);
2583
2584 end;
2585end;
2586
2587// set add level calculation in level-array (default is 0)
2588// 0 => no calcul
2589// 1 => calcul before all DSP procedures.
2590// 2 => calcul after all DSP procedures.
2591procedure Tuos_Player.InputSetLevelArrayEnable (InputIndex: cint32; levelcalc : cint32);
2592begin
2593 if (isAssigned = True) then
2594 begin
2595 if index + 1 > length (uosLevelArray) then
2596 setlength (uosLevelArray,index + 1);
2597 if InputIndex + 1 > length (uosLevelArray[index]) then
2598 setlength (uosLevelArray[index],InputIndex + 1);
2599 setlength (uosLevelArray[index][InputIndex],0);
2600 StreamIn[InputIndex].Data.levelArrayEnable := levelcalc;
2601 end;
2602end;
2603
2604// set level calculation (default is 0)
2605// 0 => no calcul
2606// 1 => calcul before all DSP procedures.
2607// 2 => calcul after all DSP procedures.
2608// 3 => calcul before and after all DSP procedures.
2609
2610procedure Tuos_Player.InputSetLevelEnable (InputIndex: cint32; levelcalc : cint32);
2611begin
2612 if (isAssigned = True) then
2613 StreamIn[InputIndex].Data.levelEnable := levelcalc;
2614end;
2615
2616// set position calculation (default is 0)
2617// 0 => no calcul
2618// 1 => calcul position procedures.
2619procedure Tuos_Player.InputSetPositionEnable (InputIndex: cint32; poscalc : cint32);
2620begin
2621 if (isAssigned = True) then
2622 StreamIn[InputIndex].Data.PositionEnable := poscalc;
2623end;
2624
2625function Tuos_Player.InputGetLevelLeft (InputIndex: cint32): double;
2626// InputIndex : InputIndex of existing input
2627// result : left level (volume) from 0 to 1
2628begin
2629 Result := 0;
2630 if (isAssigned = True) then Result := StreamIn[InputIndex].Data.LevelLeft;
2631end;
2632
2633
2634function Tuos_Player.InputGetLevelRight (InputIndex: cint32): double;
2635// InputIndex : InputIndex of existing input
2636// result : right level (volume) from 0 to 1
2637begin
2638 Result := 0;
2639 if (isAssigned = True) then Result := StreamIn[InputIndex].Data.LevelRight;
2640end;
2641
2642procedure Tuos_Player.OutputSetLevelEnable (OutputIndex: cint32; levelcalc : cint32);
2643// set level calculation (default is 0)
2644// 0 => no calcul
2645// 1 => calcul before all DSP procedures.
2646// 2 => calcul after all DSP procedures.
2647// 3 => calcul before and after all DSP procedures.
2648begin
2649 if (isAssigned = True) then
2650 StreamOut[OutputIndex].Data.levelEnable := levelcalc;
2651end;
2652
2653function Tuos_Player.OutputGetLevelLeft (OutputIndex: cint32): double;
2654// OutputIndex : OutputIndex of existing Output
2655// result : left level (volume) from 0 to 1
2656begin
2657 Result := 0;
2658 if (isAssigned = True) then Result := StreamOut[OutputIndex].Data.LevelLeft;
2659end;
2660
2661function Tuos_Player.OutputGetLevelRight (OutputIndex: cint32): double;
2662// OutputIndex : OutputIndex of existing Output
2663// result : right level (volume) from 0 to 1
2664begin
2665 Result := 0;
2666 if (isAssigned = True) then Result := StreamOut[OutputIndex].Data.LevelRight;
2667end;
2668
2669function Tuos_Player.InputFiltersGetLevelString (InputIndex: cint32): string;
2670// InputIndex : InputIndex of existing input
2671// result : list of left|right levels separed by $ character
2672begin
2673 Result := '';
2674 if (isAssigned = True) then Result := StreamIn[InputIndex].data.Levelfilters;
2675end;
2676
2677function Tuos_Player.InputFiltersGetLevelArray (InputIndex: cint32): TDArFloat;
2678// InputIndex : InputIndex of existing input
2679// result : array of float of each filter.
2680//in format levelfilter0left,levelfilter0right,levelfilter1left,levelfilter2right,...
2681begin
2682 if (isAssigned = True) then Result := StreamIn[InputIndex].data.Levelfiltersar;
2683end;
2684
2685{$IF DEFINED (soundtouch)}
2686function Tuos_Player.InputGetBPM (InputIndex: cint32): CDouble;
2687// InputIndex : InputIndex of existing input
2688// result : Beat per minuts
2689begin
2690 Result := 0;
2691 if (isAssigned = True) then Result := StreamIn[InputIndex].Data.BPM;
2692end;
2693{$endif}
2694
2695function Tuos_Player.InputPositionSeconds (InputIndex: cint32): float;
2696begin
2697 Result := 0;
2698 if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Position / StreamIn[InputIndex].
2699 Data.SampleRate;
2700end;
2701
2702function Tuos_Player.InputPositionTime (InputIndex: cint32): TTime;
2703var
2704 tmp: float = 0.0;
2705 h: word = 0;
2706 m: word = 0;
2707 s: word = 0;
2708 ms: word = 0;
2709
2710begin
2711 Result := sysutils.EncodeTime (0, 0, 0, 0);
2712 if (isAssigned = True) then
2713 begin
2714 tmp := InputPositionSeconds (InputIndex);
2715 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2716 WriteLn ('InputPositionTime (): InputPositionSeconds: '+ floattostr (tmp));
2717 {$endif}
2718 ms := trunc (frac (tmp) * 1000);
2719 h := trunc (tmp / 3600);
2720 m := trunc (tmp / 60 - h * 60);
2721 s := trunc (tmp - (h * 3600 + m * 60));
2722 Result := sysutils.EncodeTime (h, m, s, ms);
2723 end;
2724 {$IF DEFINED (uos_debug) and DEFINED (unix)}
2725 WriteLn ('EncodeTime (): '+ timetostr (Result));
2726 {$endif}
2727end;
2728
2729// for mp3 and opus files only
2730function Tuos_Player.InputUpdateTag (InputIndex: cint32): boolean;
2731
2732{$IF DEFINED (mpg123) or DEFINED (opus) }
2733var
2734 {$endif}
2735
2736 {$IF DEFINED (mpg123)}
2737 // problems with mpg123
2738 // mpinfo: Tmpg123_frameinfo;
2739 // mpid3v2: Tmpg123_id3v2;
2740 BufferTag: array[1..128] of char;
2741 F: file;
2742 {$endif}
2743
2744 {$IF DEFINED (opus)}
2745 s: UTF8String;
2746 j: Integer;
2747 OpusTag: POpusTags;
2748 LComment: PPAnsiChar;
2749 LcommentLength: PInteger;
2750 {$endif}
2751
2752begin
2753
2754 Result := false;
2755 if (isAssigned = True) then
2756 begin
2757 {$IF DEFINED (mpg123)}
2758 if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2759 begin
2760 //mpg123_info (StreamIn[InputIndex].Data.HandleSt, MPinfo);
2761 // custom code for reading ID3Tag ---> problems with mpg123_id3 ()
2762
2763 AssignFile (F, StreamIn[InputIndex].Data.Filename);
2764 FileMode := fmOpenRead + fmShareDenyNone;
2765 Reset (F, 1);
2766 Seek (F, FileSize (F) - 128);
2767 BlockRead (F, BufferTag, SizeOf (BufferTag));
2768 CloseFile (F);
2769
2770 StreamIn[InputIndex].Data.tag := copy (BufferTag, 1, 3);
2771 StreamIn[InputIndex].Data.title := copy (BufferTag, 4, 30);
2772 StreamIn[InputIndex].Data.artist := copy (BufferTag, 34, 30);
2773 StreamIn[InputIndex].Data.album := copy (BufferTag, 64, 30);
2774 StreamIn[InputIndex].Data.date := copy (BufferTag, 94, 4);
2775 StreamIn[InputIndex].Data.comment := copy (BufferTag, 98, 29);
2776 StreamIn[InputIndex].Data.track := inttostr (ord (BufferTag[127]));
2777 StreamIn[InputIndex].Data.genre := inttostr (ord (BufferTag[128]));
2778
2779 Result := true;
2780 // ? freeandnil (MPinfo);
2781 end;
2782{$endif}
2783
2784{$IF DEFINED (opus)}
2785 if StreamIn[InputIndex].Data.LibOpen = 4 then// opus
2786 begin
2787 OpusTag := op_tags (StreamIn[InputIndex].Data.HandleOP, Nil);
2788
2789 if OpusTag<>nil
2790
2791 then
2792 begin
2793
2794 if OpusTag^.comments>0
2795 then
2796 begin
2797
2798 LComment := OpusTag^.user_comments;
2799 LcommentLength := OpusTag^.comment_lengths;
2800 for j := 0 to OpusTag^.comments - 1 do
2801 begin
2802 SetLength (s, LcommentLength^);
2803 move (Pointer (LComment^)^, Pointer (s)^, LcommentLength^);
2804
2805 if j = 1 then StreamIn[InputIndex].Data.title := s;
2806 if j = 2 then StreamIn[InputIndex].Data.artist := s;
2807 if j = 3 then StreamIn[InputIndex].Data.album := s;
2808 if j = 4 then StreamIn[InputIndex].Data.date := s;
2809 if j = 5 then StreamIn[InputIndex].Data.comment := s;
2810 if j = 6 then StreamIn[InputIndex].Data.tag := s;
2811
2812 inc (LComment);
2813 inc (LcommentLength);
2814 end;
2815 result := true;
2816 end;
2817 end;
2818 end;
2819 {$endif}
2820 end;
2821end;
2822
2823{$IF DEFINED (webstream) and DEFINED (mpg123)}
2824// for mp3 files only
2825function Tuos_Player.InputUpdateICY(InputIndex: cint32; var icy_data: pchar
2826 ): integer;
2827begin
2828 Result := -1;
2829 if (isAssigned = True) then
2830 begin
2831 if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2832 if assigned (StreamIn[InputIndex].httpget) then
2833 if StreamIn[InputIndex].httpget.ICYenabled = true then
2834 begin
2835 Result := mpg123_icy(StreamIn[InputIndex].Data.HandleSt, icy_data);
2836 end;
2837 end;
2838end;
2839{$endif}
2840
2841{$IF DEFINED (webstream)}
2842// Type of audio of url stream, 0:mp3, 1:opus, 2:acc
2843function Tuos_Player.InputGetURLAudioType(InputIndex: cint32): integer;
2844begin
2845 Result := -1;
2846 if (isAssigned = True) then
2847 begin
2848 // if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2849 if assigned (StreamIn[InputIndex].httpget) then
2850 Result := StreamIn[InputIndex].httpget.FormatType -1;
2851 end;
2852end;
2853
2854function Tuos_Player.InputGetURLContentType(InputIndex: cint32): string;
2855begin
2856 Result := '';
2857 if (isAssigned = True) then
2858 begin
2859 //if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2860 if assigned (StreamIn[InputIndex].httpget) then
2861 Result := StreamIn[InputIndex].httpget.ContentType;
2862 end;
2863end;
2864
2865function Tuos_Player.InputGetURLiceAudioInfo(InputIndex: cint32): string;
2866begin
2867 Result := '';
2868 if (isAssigned = True) then
2869 begin
2870 //if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2871 if assigned (StreamIn[InputIndex].httpget) then
2872 Result := StreamIn[InputIndex].httpget.ice_Audio_Info;
2873 end;
2874end;
2875
2876function Tuos_Player.InputGetURLicyDescription(InputIndex: cint32): string;
2877begin
2878 Result := '';
2879 if (isAssigned = True) then
2880 begin
2881 //if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2882 if assigned (StreamIn[InputIndex].httpget) then
2883 Result := StreamIn[InputIndex].httpget.icy_description;
2884 end;
2885end;
2886function Tuos_Player.InputGetURLicyGenre(InputIndex: cint32): string;
2887begin
2888 Result := '';
2889 if (isAssigned = True) then
2890 begin
2891 //if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2892 if assigned (StreamIn[InputIndex].httpget) then
2893 Result := StreamIn[InputIndex].httpget.icy_genre;
2894 end;
2895end;
2896function Tuos_Player.InputGetURLicyName(InputIndex: cint32): string;
2897begin
2898 Result := '';
2899 if (isAssigned = True) then
2900 begin
2901 //if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2902 if assigned (StreamIn[InputIndex].httpget) then
2903 Result := StreamIn[InputIndex].httpget.icy_name;
2904 end;
2905end;
2906function Tuos_Player.InputGetURLicyUrl(InputIndex: cint32): string;
2907begin
2908 Result := '';
2909 if (isAssigned = True) then
2910 begin
2911 //if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
2912 if assigned (StreamIn[InputIndex].httpget) then
2913 Result := StreamIn[InputIndex].httpget.icy_url;
2914 end;
2915end;
2916{$ENDIF}
2917
2918function Tuos_Player.InputGetTagTitle (InputIndex: cint32): pchar;
2919begin
2920 Result := Nil;
2921 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.title);
2922end;
2923
2924function Tuos_Player.InputGetTagArtist (InputIndex: cint32): pchar;
2925begin
2926 Result := Nil;
2927 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.Artist);
2928end;
2929
2930function Tuos_Player.InputGetTagAlbum (InputIndex: cint32): pchar;
2931begin
2932 Result := Nil;
2933 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.album);
2934end;
2935
2936function Tuos_Player.InputGetTagComment (InputIndex: cint32): pchar;
2937begin
2938 Result := Nil;
2939 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.comment);
2940end;
2941
2942function Tuos_Player.InputGetTagTrack (InputIndex: cint32): pchar;
2943begin
2944 Result := Nil;
2945 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.track);
2946end;
2947
2948function Tuos_Player.InputGetTagGenre (InputIndex: cint32): pchar;
2949begin
2950 Result := Nil;
2951 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.genre);
2952end;
2953
2954function Tuos_Player.InputGetTagTag (InputIndex: cint32): pchar;
2955begin
2956 Result := Nil;
2957 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.tag);
2958end;
2959
2960function Tuos_Player.InputGetTagDate (InputIndex: cint32): pchar;
2961begin
2962 Result := Nil;
2963 if (isAssigned = True) then Result := pchar (StreamIn[InputIndex].Data.date);
2964end;
2965
2966procedure Tuos_Player.InputSetDSP (InputIndex: cint32; DSPinIndex: cint32;
2967 Enable: boolean);
2968begin
2969 StreamIn[InputIndex].DSP[DSPinIndex].Enabled := Enable;
2970end;
2971
2972procedure Tuos_Player.OutPutSetDSP(OutputIndex: cint32; DSPoutIndex: cint32;
2973 Enable: boolean);
2974begin
2975 StreamOut[OutputIndex].DSP[DSPoutIndex].Enabled := Enable;
2976end;
2977
2978function Tuos_Player.InputAddDSP (InputIndex: cint32; BeforeFunc: TFunc;
2979 AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc ): cint32;
2980begin
2981 Result := Length (StreamIn[InputIndex].DSP);
2982 SetLength (StreamIn[InputIndex].DSP, Result + 1);
2983
2984 StreamIn[InputIndex].DSP[Result] := Tuos_DSP.Create ();
2985 StreamIn[InputIndex].DSP[Result].Enabled := false;
2986 StreamIn[InputIndex].DSP[Result].BefFunc := BeforeFunc;
2987 StreamIn[InputIndex].DSP[Result].AftFunc := AfterFunc;
2988 StreamIn[InputIndex].DSP[Result].EndFunc := EndedFunc;
2989 StreamIn[InputIndex].DSP[Result].LoopProc := LoopProc;
2990 StreamIn[InputIndex].DSP[Result].Enabled := True;
2991end;
2992
2993procedure Tuos_Player.OutputSetEnable (OutputIndex: cint32; enabled: boolean);
2994// set enable true or false
2995begin
2996 StreamOut[OutputIndex].data.Enabled := enabled;
2997end;
2998
2999function Tuos_Player.OutputAddDSP (OutputIndex: cint32; BeforeFunc: TFunc;
3000 AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc): cint32;
3001begin
3002 Result := Length (StreamOut[OutputIndex].DSP);
3003 SetLength (StreamOut[OutputIndex].DSP, Result + 1);
3004 StreamOut[OutputIndex].DSP[Result] := Tuos_DSP.Create;
3005 StreamOut[OutputIndex].DSP[Result].Enabled := false;
3006 StreamOut[OutputIndex].DSP[Result].BefFunc := BeforeFunc;
3007 StreamOut[OutputIndex].DSP[Result].AftFunc := AfterFunc;
3008 StreamOut[OutputIndex].DSP[Result].EndFunc := EndedFunc;
3009 StreamOut[OutputIndex].DSP[Result].LoopProc := LoopProc;
3010 StreamOut[OutputIndex].DSP[Result].Enabled := True;
3011end;
3012
3013
3014// InputIndex : InputIndex of an existing Input
3015// DSPInIndex : DSPInIndex of existing DSPIn
3016// TypeFilterL: Type of filter left:
3017// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
3018// LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
3019// HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
3020// GainL : gain left to apply to filter
3021// TypeFilterR: Type of filter right (ignored if mono):
3022// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
3023// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
3024// HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
3025// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
3026// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
3027// LoopProc : external procedure of object to synchronize after DSP done
3028// Enable : Filter enabled
3029procedure Tuos_Player.InputSetFilter (InputIndex: cint32; FilterIndex: cint32;
3030 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
3031 cfloat;
3032 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
3033 cfloat;
3034 AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
3035begin
3036 if isAssigned = true then
3037 begin
3038 StreamIn[InputIndex].DSP[FilterIndex].fftdata.AlsoBuf := AlsoBuf;
3039 StreamIn[InputIndex].DSP[FilterIndex].Enabled := Enable;
3040
3041 if LowFrequencyL = -1 then
3042 LowFrequencyL := StreamIn[InputIndex].DSP[FilterIndex].fftdata.LowFrequencyL;
3043 if LowFrequencyL = -1 then
3044 LowFrequencyL := StreamIn[InputIndex].DSP[FilterIndex].fftdata.HighFrequencyL;
3045 if GainL <> -1 then
3046 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Gainl := cfloat (Gainl);
3047
3048 if LowFrequencyR = -1 then
3049 LowFrequencyR := StreamIn[InputIndex].DSP[FilterIndex].fftdata.LowFrequencyR;
3050 if LowFrequencyR = -1 then
3051 LowFrequencyR := StreamIn[InputIndex].DSP[FilterIndex].fftdata.HighFrequencyR;
3052 if GainR <> -1 then
3053 StreamIn[InputIndex].DSP[FilterIndex].fftdata.GainR := cfloat (GainR);
3054
3055 if TypeFilterL <> -1 then
3056 begin
3057 StreamIn[InputIndex].DSP[FilterIndex].fftdata.typefilterL := TypeFilterL;
3058 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C := 0.0;
3059 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D := 0.0;
3060 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] := 0.0;
3061 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
3062 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] := 0.0;
3063 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] := 0.0;
3064 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] := 0.0;
3065 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2 := 0.0;
3066 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2 := 0.0;
3067 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[0] := 0.0;
3068 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
3069 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[2] := 0.0;
3070 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[0] := 0.0;
3071 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[1] := 0.0;
3072
3073 case TypeFilterL of
3074 1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
3075 begin
3076 // DSPFFTBandReject
3077
3078 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
3079 Tan (Pi * (HighFrequencyL -
3080 LowFrequencyl + 1) /
3081 StreamIn[InputIndex].Data.
3082 SampleRate);
3083 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D :=
3084 2 * Cos (2 * Pi * (roundmath (
3085 HighFrequencyl + LowFrequencyl)
3086 shr 1) /
3087 StreamIn[InputIndex].Data.
3088 SampleRate);
3089 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3090 1 / (1 + StreamIn[InputIndex
3091 ].DSP[FilterIndex].fftdata.C
3092 );
3093 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3094 -StreamIn[InputIndex].DSP[
3095 FilterIndex].fftdata.D *
3096 StreamIn[InputIndex].DSP[
3097 FilterIndex].fftdata.a3[0];
3098 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3099 StreamIn[InputIndex].DSP[
3100 FilterIndex].fftdata.a3[0];
3101 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3102 StreamIn[InputIndex].DSP[
3103 FilterIndex].fftdata.a3[1];
3104 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3105 (1 - StreamIn[InputIndex].
3106 DSP[FilterIndex].fftdata.C)
3107 *
3108 StreamIn[InputIndex].DSP[
3109 FilterIndex].fftdata.a3[0];
3110 // DSPFFTBandPass
3111 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2 :=
3112 1 / Tan (Pi * (HighFrequencyl -
3113 LowFrequencyl + 1) /
3114 StreamIn[InputIndex].Data.
3115 SampleRate);
3116 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2 :=
3117 2 * Cos (2 * Pi * (roundmath (
3118 HighFrequencyl + LowFrequencyl)
3119 shr 1) /
3120 StreamIn[InputIndex].Data.
3121 SampleRate);
3122 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[0] :=
3123 1 / (1 + StreamIn[
3124 InputIndex].DSP[FilterIndex
3125 ].fftdata.C2);
3126 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
3127 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[2] :=
3128 -StreamIn[InputIndex].DSP[
3129 FilterIndex].fftdata.a32[0];
3130
3131 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[0] :=
3132 -StreamIn[InputIndex].DSP[
3133 FilterIndex].fftdata.C2 *
3134 StreamIn[InputIndex].DSP[
3135 FilterIndex].fftdata.D2 *
3136 StreamIn[InputIndex].DSP[
3137 FilterIndex].fftdata.a32[0];
3138
3139 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[1] :=
3140 (StreamIn[InputIndex].DSP[
3141 FilterIndex].fftdata.C2 - 1
3142 ) *
3143 StreamIn[InputIndex].DSP[
3144 FilterIndex].fftdata.a32[0];
3145
3146 end;
3147
3148 2: // DSPFFTBandReject
3149 begin
3150 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
3151 Tan (Pi * (HighFrequencyl -
3152 LowFrequencyl + 1) /
3153 StreamIn[InputIndex].Data.
3154 SampleRate);
3155 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D :=
3156 2 * Cos (2 * Pi * (roundmath (
3157 HighFrequencyl + LowFrequencyl)
3158 shr 1) /
3159 StreamIn[InputIndex].Data.
3160 SampleRate);
3161 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3162 1 / (1 + StreamIn[InputIndex
3163 ].DSP[FilterIndex].fftdata.C);
3164
3165 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3166 -StreamIn[InputIndex].DSP[
3167 FilterIndex].fftdata.D *
3168 StreamIn[InputIndex].DSP[
3169 FilterIndex].fftdata.a3[0];
3170 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3171 StreamIn[InputIndex].DSP[
3172 FilterIndex].fftdata.a3[0];
3173 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3174 StreamIn[InputIndex].DSP[
3175 FilterIndex].fftdata.a3[1];
3176 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3177 (1 - StreamIn[InputIndex].
3178 DSP[FilterIndex].fftdata.C)
3179 *
3180 StreamIn[InputIndex].DSP[
3181 FilterIndex].fftdata.a3[0];
3182 end;
3183
3184 3: // DSPFFTBandPass
3185 begin
3186
3187 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
3188 1 / Tan (Pi * (HighFrequencyl -
3189 LowFrequencyl + 1) /
3190 StreamIn[InputIndex].Data.
3191 SampleRate);
3192 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D :=
3193 2 * Cos (2 * Pi * (roundmath (
3194 HighFrequencyl + LowFrequencyl)
3195 shr 1) /
3196 StreamIn[InputIndex].Data.
3197 SampleRate);
3198 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3199 1 / (1 + StreamIn[InputIndex
3200 ].DSP[FilterIndex].fftdata.C
3201 );
3202 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
3203 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3204 -StreamIn[InputIndex].DSP[
3205 FilterIndex].fftdata.a3[0];
3206 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3207 -StreamIn[InputIndex].DSP[
3208 FilterIndex].fftdata.C *
3209 StreamIn[InputIndex].DSP[
3210 FilterIndex].fftdata.D *
3211 StreamIn[InputIndex].DSP[
3212 FilterIndex].fftdata.a3[0];
3213 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3214 (StreamIn[InputIndex].DSP[
3215 FilterIndex].fftdata.C - 1)
3216 *
3217 StreamIn[InputIndex].DSP[
3218 FilterIndex].fftdata.a3[0];
3219 end;
3220
3221 4: // DSPFFTLowPass
3222 begin
3223
3224 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
3225 1 / Tan (Pi * LowFrequencyl /
3226 StreamIn[InputIndex].Data.
3227 SampleRate);
3228
3229 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3230 1 / (1 + Sqrt (2) * StreamIn
3231 [
3232 InputIndex].DSP[FilterIndex]
3233 .fftdata.C +
3234 StreamIn[InputIndex].DSP[
3235 FilterIndex].fftdata.C *
3236 StreamIn[InputIndex].DSP[
3237 FilterIndex].fftdata.C);
3238 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3239 2 * StreamIn[InputIndex].DSP
3240 [FilterIndex].fftdata.a3[0];
3241 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3242 StreamIn[InputIndex].DSP[
3243 FilterIndex].fftdata.a3[0];
3244 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3245 2 * (1 - StreamIn[InputIndex
3246 ].DSP[FilterIndex].fftdata.C
3247 *
3248 StreamIn[InputIndex].DSP[
3249 FilterIndex].fftdata.C) *
3250 StreamIn[InputIndex].DSP[
3251 FilterIndex].fftdata.a3[0];
3252 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3253 (1 - Sqrt (2) * StreamIn[
3254 InputIndex].DSP[FilterIndex]
3255 .fftdata.C +
3256 StreamIn[InputIndex].DSP[
3257 FilterIndex].fftdata.C *
3258 StreamIn[InputIndex].DSP[
3259 FilterIndex].fftdata.C) *
3260 StreamIn[InputIndex].DSP[
3261 FilterIndex].fftdata.a3[0];
3262 end;
3263
3264 5: // DSPFFTHighPass
3265 begin
3266 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
3267 Tan (Pi * HighFrequencyl /
3268 StreamIn[InputIndex].Data.
3269 SampleRate);
3270
3271 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3272 1 / (1 + Sqrt (2) * StreamIn
3273 [
3274 InputIndex].DSP[FilterIndex]
3275 .fftdata.C +
3276 StreamIn[InputIndex].DSP[
3277 FilterIndex].fftdata.C *
3278 StreamIn[InputIndex].DSP[
3279 FilterIndex].fftdata.C);
3280 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3281
3282 -2 * StreamIn[InputIndex].
3283 DSP[FilterIndex].fftdata.a3[
3284 0];
3285 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3286 StreamIn[InputIndex].DSP[
3287 FilterIndex].fftdata.a3[0];
3288 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3289 2 * (StreamIn[InputIndex].
3290 DSP[FilterIndex].fftdata.C *
3291 StreamIn[InputIndex].DSP[
3292 FilterIndex].fftdata.C - 1)
3293 *
3294 StreamIn[InputIndex].DSP[
3295 FilterIndex].fftdata.a3[0];
3296 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3297 (1 - Sqrt (2) * StreamIn[
3298 InputIndex].DSP[FilterIndex]
3299 .fftdata.C +
3300 StreamIn[InputIndex].DSP[
3301 FilterIndex].fftdata.C *
3302 StreamIn[InputIndex].DSP[
3303 FilterIndex].fftdata.C) *
3304 StreamIn[InputIndex].DSP[
3305 FilterIndex].fftdata.a3[0];
3306 end;
3307 end;
3308 end;
3309
3310 if TypeFilterR <> -1 then
3311 begin
3312 StreamIn[InputIndex].DSP[FilterIndex].fftdata.typefilterR := TypeFilterR;
3313 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr := 0.0;
3314 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr := 0.0;
3315 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] := 0.0;
3316 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
3317 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] := 0.0;
3318 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] := 0.0;
3319 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] := 0.0;
3320 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2r := 0.0;
3321 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2r := 0.0;
3322 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[0] := 0.0;
3323 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
3324 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[2] := 0.0;
3325 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[0] := 0.0;
3326 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[1] := 0.0;
3327
3328 case TypeFilterR of
3329 1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
3330 begin
3331 // DSPFFTBandReject
3332 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
3333 Tan (Pi * (HighFrequencyr -
3334 LowFrequencyr + 1) /
3335 StreamIn[InputIndex].Data.
3336 SampleRate);
3337 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr :=
3338 2 * Cos (2 * Pi * (roundmath (
3339 HighFrequencyr + LowFrequencyr)
3340 shr 1) /
3341 StreamIn[InputIndex].Data.
3342 SampleRate);
3343 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
3344 1 / (1 + StreamIn[
3345 InputIndex].DSP[FilterIndex
3346 ].fftdata.Cr);
3347 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
3348 -StreamIn[InputIndex].DSP[
3349 FilterIndex].fftdata.Dr *
3350 StreamIn[InputIndex].DSP[
3351 FilterIndex].fftdata.a3r[0]
3352 ;
3353 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
3354 StreamIn[InputIndex].DSP[
3355 FilterIndex].fftdata.a3r[0]
3356 ;
3357 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
3358 StreamIn[InputIndex].DSP[
3359 FilterIndex].fftdata.a3r[1]
3360 ;
3361 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
3362 (1 - StreamIn[InputIndex].
3363 DSP[FilterIndex].fftdata.Cr
3364 ) *
3365 StreamIn[InputIndex].DSP[
3366 FilterIndex].fftdata.a3r[0]
3367 ;
3368 // DSPFFTBandPass
3369 StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2r :=
3370 1 / Tan (Pi * (HighFrequencyr
3371 -
3372 LowFrequencyr + 1) /
3373 StreamIn[InputIndex].Data.
3374 SampleRate);
3375 StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2r :=
3376 2 * Cos (2 * Pi * (roundmath (
3377 HighFrequencyr + LowFrequencyr
3378 ) shr 1) /
3379 StreamIn[InputIndex].Data.
3380 SampleRate);
3381 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[0] :=
3382 1 / (1 + StreamIn[
3383 InputIndex].DSP[
3384 FilterIndex].fftdata.C2r);
3385 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
3386 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[2] :=
3387 -StreamIn[InputIndex].DSP[
3388 FilterIndex].fftdata.a32r[
3389 0];
3390 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[0] :=
3391 -StreamIn[InputIndex].DSP[
3392 FilterIndex].fftdata.C2r *
3393 StreamIn[InputIndex].DSP[
3394 FilterIndex].fftdata.D2r *
3395 StreamIn[InputIndex].DSP[
3396 FilterIndex].fftdata.a32r[
3397 0];
3398 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[1] :=
3399 (StreamIn[InputIndex].DSP[
3400 FilterIndex].fftdata.C2r -
3401 1) *
3402 StreamIn[InputIndex].DSP[
3403 FilterIndex].fftdata.a32r[
3404 0];
3405
3406 end;
3407
3408 2: // DSPFFTBandReject
3409 begin
3410 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
3411 Tan (Pi * (HighFrequencyr -
3412 LowFrequencyr + 1) /
3413 StreamIn[InputIndex].Data.
3414 SampleRate);
3415 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr :=
3416 2 * Cos (2 * Pi * (roundmath (
3417 HighFrequencyr + LowFrequencyr)
3418 shr 1) /
3419 StreamIn[InputIndex].Data.
3420 SampleRate);
3421 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
3422 1 / (1 + StreamIn[
3423 InputIndex].DSP[FilterIndex
3424 ].fftdata.Cr);
3425 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
3426 -StreamIn[InputIndex].DSP[
3427 FilterIndex].fftdata.Dr *
3428 StreamIn[InputIndex].DSP[
3429 FilterIndex].fftdata.a3r[0];
3430
3431 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
3432 StreamIn[InputIndex].DSP[
3433 FilterIndex].fftdata.a3r[0];
3434
3435 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
3436 StreamIn[InputIndex].DSP[
3437 FilterIndex].fftdata.a3r[1];
3438
3439 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
3440 (1 - StreamIn[InputIndex].
3441 DSP[FilterIndex].fftdata.Cr
3442 ) *
3443 StreamIn[InputIndex].DSP[
3444 FilterIndex].fftdata.a3r[0];
3445
3446 end;
3447
3448 3: // DSPFFTBandPass
3449 begin
3450
3451 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
3452 1 / Tan (Pi * (HighFrequencyr-
3453 LowFrequencyr + 1) /
3454 StreamIn[InputIndex].Data.
3455 SampleRate);
3456 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr :=
3457 2 * Cos (2 * Pi * (roundmath (
3458 HighFrequencyr + LowFrequencyr)
3459 shr 1) /
3460 StreamIn[InputIndex].Data.
3461 SampleRate);
3462 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
3463 1 / (1 + StreamIn[
3464 InputIndex].DSP[FilterIndex
3465 ].fftdata.Cr);
3466 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
3467 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
3468 -StreamIn[InputIndex].DSP[
3469 FilterIndex].fftdata.a3r[0];
3470
3471 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
3472 -StreamIn[InputIndex].DSP[
3473 FilterIndex].fftdata.Cr *
3474 StreamIn[InputIndex].DSP[
3475 FilterIndex].fftdata.Dr *
3476 StreamIn[InputIndex].DSP[
3477 FilterIndex].fftdata.a3r[0];
3478
3479 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
3480 (StreamIn[InputIndex].DSP[
3481 FilterIndex].fftdata.Cr - 1
3482 ) *
3483 StreamIn[InputIndex].DSP[
3484 FilterIndex].fftdata.a3r[0];
3485 end;
3486
3487 4: // DSPFFTLowPass
3488 begin
3489
3490 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
3491 1 / Tan (Pi * LowFrequencyr /
3492 StreamIn[InputIndex].Data.
3493 SampleRate);
3494
3495 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
3496 1 / (1 + Sqrt (2) *
3497 StreamIn
3498 [InputIndex].DSP[
3499 FilterIndex].fftdata.Cr +
3500 StreamIn[InputIndex].DSP[
3501 FilterIndex].fftdata.Cr *
3502 StreamIn[InputIndex].DSP[
3503 FilterIndex].fftdata.Cr);
3504 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
3505 2 * StreamIn[InputIndex].
3506 DSP[FilterIndex].fftdata.
3507 a3r[0];
3508 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
3509 StreamIn[InputIndex].DSP[
3510 FilterIndex].fftdata.a3r[0];
3511 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
3512 2 * (1 - StreamIn[
3513 InputIndex].DSP[FilterIndex
3514 ].fftdata.Cr *
3515 StreamIn[InputIndex].DSP[
3516 FilterIndex].fftdata.Cr) *
3517 StreamIn[InputIndex].DSP[
3518 FilterIndex].fftdata.a3r[0];
3519 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
3520 (1 - Sqrt (2) * StreamIn[
3521 InputIndex].DSP[FilterIndex
3522 ].fftdata.Cr +
3523 StreamIn[InputIndex].DSP[
3524 FilterIndex].fftdata.Cr *
3525 StreamIn[InputIndex].DSP[
3526 FilterIndex].fftdata.Cr) *
3527 StreamIn[InputIndex].DSP[
3528 FilterIndex].fftdata.a3r[0];
3529 end;
3530
3531 5: // DSPFFTHighPass
3532 begin
3533 StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
3534 Tan (Pi * HighFrequencyr /
3535 StreamIn[InputIndex].Data.
3536 SampleRate);
3537
3538 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
3539 1 / (1 + Sqrt (2) *
3540 StreamIn
3541 [InputIndex].DSP[
3542 FilterIndex].fftdata.Cr +
3543 StreamIn[InputIndex].DSP[
3544 FilterIndex].fftdata.Cr *
3545 StreamIn[InputIndex].DSP[
3546 FilterIndex].fftdata.Cr);
3547 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
3548
3549 -2 * StreamIn[InputIndex].
3550 DSP[FilterIndex].fftdata.
3551 a3r[0];
3552 StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
3553 StreamIn[InputIndex].DSP[
3554 FilterIndex].fftdata.a3r[0];
3555 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
3556 2 * (StreamIn[InputIndex].
3557 DSP[FilterIndex].fftdata.Cr
3558 *
3559 StreamIn[InputIndex].DSP[
3560 FilterIndex].fftdata.Cr - 1
3561 ) *
3562 StreamIn[InputIndex].DSP[
3563 FilterIndex].fftdata.a3r[0];
3564 StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
3565 (1 - Sqrt (2) * StreamIn[
3566 InputIndex].DSP[FilterIndex
3567 ].fftdata.Cr +
3568 StreamIn[InputIndex].DSP[
3569 FilterIndex].fftdata.Cr *
3570 StreamIn[InputIndex].DSP[
3571 FilterIndex].fftdata.Cr) *
3572 StreamIn[InputIndex].DSP[
3573 FilterIndex].fftdata.a3r[0];
3574 end;
3575 end;
3576 end;
3577 end;
3578end;
3579
3580// OuputIndex : InputIndex of an existing Output
3581// DSPInIndex : DSPInIndex of existing DSPIn
3582// TypeFilterL: Type of filter left:
3583// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
3584// fBandPass = 3, fLowPass = 4, fHighPass = 5)
3585// LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
3586// HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
3587// GainL : gain left to apply to filter
3588// TypeFilterR: Type of filter right (ignored if mono):
3589// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
3590// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
3591// HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
3592// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
3593// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
3594// LoopProc : external procedure of object to synchronize after DSP done
3595// Enable : Filter enabled
3596procedure Tuos_Player.OutputSetFilter (OutputIndex: cint32; FilterIndex: cint32;
3597 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
3598 cfloat;
3599 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
3600 cfloat;
3601 AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
3602begin
3603 if isAssigned = true then
3604 begin
3605 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.AlsoBuf := AlsoBuf;
3606 StreamOut[OutputIndex].DSP[FilterIndex].Enabled := Enable;
3607
3608 if LowFrequencyL = -1 then
3609 LowFrequencyL := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.LowFrequencyL;
3610 if LowFrequencyL = -1 then
3611 LowFrequencyL := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.HighFrequencyL;
3612 if GainL <> -1 then
3613 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Gainl := cfloat (Gainl);
3614
3615 if LowFrequencyR = -1 then
3616 LowFrequencyR := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.LowFrequencyR;
3617 if LowFrequencyR = -1 then
3618 LowFrequencyR := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.HighFrequencyR;
3619 if GainR <> -1 then
3620 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.GainR := cfloat (GainR);
3621
3622 if TypeFilterL <> -1 then
3623 begin
3624 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.typefilterL := TypeFilterL;
3625 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C := 0.0;
3626 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D := 0.0;
3627 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] := 0.0;
3628 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
3629 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] := 0.0;
3630 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] := 0.0;
3631 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] := 0.0;
3632 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2 := 0.0;
3633 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2 := 0.0;
3634 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[0] := 0.0;
3635 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
3636 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[2] := 0.0;
3637 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[0] := 0.0;
3638 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[1] := 0.0;
3639
3640 case TypeFilterL of
3641 1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
3642 begin
3643 // DSPFFTBandReject
3644
3645 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
3646 Tan (Pi * (HighFrequencyL -
3647 LowFrequencyl + 1) /
3648 StreamOut[OutputIndex].Data.
3649 SampleRate);
3650 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D :=
3651 2 * Cos (2 * Pi * (roundmath (
3652 HighFrequencyl + LowFrequencyl
3653 ) shr 1) /
3654 StreamOut[OutputIndex].Data.
3655 SampleRate);
3656 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3657 1 / (1 + StreamOut[
3658 OutputIndex].DSP[
3659 FilterIndex].fftdata.C);
3660 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3661 -StreamOut[OutputIndex].
3662 DSP[FilterIndex].fftdata.D
3663 *
3664 StreamOut[OutputIndex].DSP
3665 [FilterIndex].fftdata.a3[0
3666 ];
3667 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3668 StreamOut[OutputIndex].DSP
3669 [FilterIndex].fftdata.a3[0
3670 ];
3671 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3672 StreamOut[OutputIndex].DSP
3673 [FilterIndex].fftdata.a3[1
3674 ];
3675 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3676 (1 - StreamOut[OutputIndex
3677 ].DSP[FilterIndex].fftdata
3678 .C) *
3679 StreamOut[OutputIndex].DSP
3680 [FilterIndex].fftdata.a3[0
3681 ];
3682 // DSPFFTBandPass
3683 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2 :=
3684 1 / Tan (Pi * (HighFrequencyl
3685 - LowFrequencyl + 1) /
3686 StreamOut[OutputIndex].Data.
3687 SampleRate);
3688 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2 :=
3689 2 * Cos (2 * Pi * (roundmath
3690 (
3691 HighFrequencyl +
3692 LowFrequencyl) shr 1) /
3693 StreamOut[OutputIndex].Data.
3694 SampleRate);
3695 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[0] :=
3696 1 / (1 + StreamOut[
3697 OutputIndex].DSP[
3698 FilterIndex].fftdata.C2);
3699 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
3700 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[2] :=
3701 -StreamOut[OutputIndex].
3702 DSP[FilterIndex].fftdata.
3703 a32[0];
3704 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[0] :=
3705 -StreamOut[OutputIndex].
3706 DSP[FilterIndex].fftdata.
3707 C2 *
3708 StreamOut[OutputIndex].
3709 DSP[FilterIndex].fftdata.
3710 D2 *
3711 StreamOut[OutputIndex].
3712 DSP[FilterIndex].fftdata.
3713 a32[0];
3714 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[1] :=
3715 (StreamOut[OutputIndex].
3716 DSP[FilterIndex].fftdata.
3717 C2 - 1) *
3718 StreamOut[OutputIndex].
3719 DSP[FilterIndex].fftdata.
3720 a32[0];
3721
3722 end;
3723
3724 2: // DSPFFTBandReject
3725 begin
3726 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
3727 Tan (Pi * (HighFrequencyl -
3728 LowFrequencyl + 1) /
3729 StreamOut[OutputIndex].Data.
3730 SampleRate);
3731 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D :=
3732 2 * Cos (2 * Pi * (roundmath (
3733 HighFrequencyl + LowFrequencyl
3734 ) shr 1) /
3735 StreamOut[OutputIndex].Data.
3736 SampleRate);
3737 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3738 1 / (1 + StreamOut[
3739 OutputIndex].DSP[
3740 FilterIndex].fftdata.C);
3741 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3742 -StreamOut[OutputIndex].
3743 DSP[FilterIndex].fftdata.D
3744 *
3745 StreamOut[OutputIndex].DSP
3746 [FilterIndex].fftdata.a3[0
3747 ];
3748 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3749 StreamOut[OutputIndex].DSP
3750 [FilterIndex].fftdata.a3[0
3751 ];
3752 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3753 StreamOut[OutputIndex].DSP
3754 [FilterIndex].fftdata.a3[1
3755 ];
3756 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3757 (1 - StreamOut[OutputIndex
3758 ].DSP[FilterIndex].fftdata
3759 .C) *
3760 StreamOut[OutputIndex].DSP
3761 [FilterIndex].fftdata.a3[0
3762 ];
3763 end;
3764
3765 3: // DSPFFTBandPass
3766 begin
3767
3768 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
3769 1 / Tan (Pi * (HighFrequencyl
3770 -
3771 LowFrequencyl + 1) /
3772 StreamOut[OutputIndex].Data.
3773 SampleRate);
3774 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D :=
3775 2 * Cos (2 * Pi * (roundmath (
3776 HighFrequencyl + LowFrequencyl
3777 ) shr 1) /
3778 StreamOut[OutputIndex].Data.
3779 SampleRate);
3780 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3781 1 / (1 + StreamOut[
3782 OutputIndex].DSP[
3783 FilterIndex].fftdata.C);
3784 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
3785 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3786 -StreamOut[OutputIndex].
3787 DSP[FilterIndex].fftdata.
3788 a3[0];
3789 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3790 -StreamOut[OutputIndex].
3791 DSP[FilterIndex].fftdata.C
3792 *
3793 StreamOut[OutputIndex].DSP
3794 [FilterIndex].fftdata.D *
3795 StreamOut[OutputIndex].DSP
3796 [FilterIndex].fftdata.a3[0
3797 ];
3798 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3799 (StreamOut[OutputIndex].
3800 DSP[FilterIndex].fftdata.C
3801 - 1) *
3802 StreamOut[OutputIndex].DSP
3803 [FilterIndex].fftdata.a3[0
3804 ];
3805 end;
3806
3807 4: // DSPFFTLowPass
3808 begin
3809
3810 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
3811 1 / Tan (Pi * LowFrequencyl /
3812 StreamOut[OutputIndex].Data.
3813 SampleRate);
3814
3815 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3816 1 / (1 + Sqrt (2) *
3817 StreamOut[OutputIndex].DSP
3818 [FilterIndex].fftdata.C +
3819 StreamOut[OutputIndex].DSP
3820 [FilterIndex].fftdata.C *
3821 StreamOut[OutputIndex].DSP
3822 [FilterIndex].fftdata.C);
3823 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3824 2 * StreamOut[OutputIndex]
3825 .DSP[FilterIndex].fftdata.
3826 a3[0];
3827 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3828 StreamOut[OutputIndex].DSP
3829 [FilterIndex].fftdata.a3[0
3830 ];
3831 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3832 2 * (1 - StreamOut[
3833 OutputIndex].DSP[
3834 FilterIndex].fftdata.C *
3835 StreamOut[OutputIndex].DSP
3836 [FilterIndex].fftdata.C) *
3837 StreamOut[OutputIndex].DSP
3838 [FilterIndex].fftdata.a3[0
3839 ];
3840 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3841 (1 - Sqrt (2) * StreamOut[
3842 OutputIndex].DSP[
3843 FilterIndex].fftdata.C +
3844 StreamOut[OutputIndex].DSP
3845 [FilterIndex].fftdata.C *
3846 StreamOut[OutputIndex].DSP
3847 [FilterIndex].fftdata.C) *
3848 StreamOut[OutputIndex].DSP
3849 [FilterIndex].fftdata.a3[0
3850 ];
3851 end;
3852
3853 5: // DSPFFTHighPass
3854 begin
3855 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
3856 Tan (Pi * HighFrequencyl /
3857 StreamOut[OutputIndex].Data.
3858 SampleRate);
3859
3860 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
3861 1 / (1 + Sqrt (2) *
3862 StreamOut[OutputIndex].DSP
3863 [FilterIndex].fftdata.C +
3864 StreamOut[OutputIndex].DSP
3865 [FilterIndex].fftdata.C *
3866 StreamOut[OutputIndex].DSP
3867 [FilterIndex].fftdata.C);
3868 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
3869
3870 -2 * StreamOut[OutputIndex
3871 ].DSP[FilterIndex].fftdata
3872 .a3[0];
3873 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
3874 StreamOut[OutputIndex].DSP
3875 [FilterIndex].fftdata.a3[0
3876 ];
3877 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
3878 2 * (StreamOut[OutputIndex
3879 ].DSP[FilterIndex].fftdata
3880 .C *
3881 StreamOut[OutputIndex].DSP
3882 [FilterIndex].fftdata.C -
3883 1) *
3884 StreamOut[OutputIndex].DSP
3885 [FilterIndex].fftdata.a3[0
3886 ];
3887 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
3888 (1 - Sqrt (2) * StreamOut[
3889 OutputIndex].DSP[
3890 FilterIndex].fftdata.C +
3891 StreamOut[OutputIndex].DSP
3892 [FilterIndex].fftdata.C *
3893 StreamOut[OutputIndex].DSP
3894 [FilterIndex].fftdata.C) *
3895 StreamOut[OutputIndex].DSP
3896 [FilterIndex].fftdata.a3[0
3897 ];
3898 end;
3899 end;
3900 end;
3901
3902 if TypeFilterR <> -1 then
3903 begin
3904 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.typefilterR := TypeFilterR;
3905 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr := 0.0;
3906 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr := 0.0;
3907 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] := 0.0;
3908 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
3909 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] := 0.0;
3910 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] := 0.0;
3911 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] := 0.0;
3912 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2r := 0.0;
3913 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2r := 0.0;
3914 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[0] := 0.0;
3915 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
3916 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[2] := 0.0;
3917 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[0] := 0.0;
3918 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[1] := 0.0;
3919
3920 case TypeFilterR of
3921 1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
3922 begin
3923 // DSPFFTBandReject
3924 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
3925 Tan (Pi * (HighFrequencyr -
3926 LowFrequencyr + 1) /
3927 StreamOut[OutputIndex].Data.
3928 SampleRate);
3929 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr :=
3930 2 * Cos (2 * Pi * (roundmath
3931 (
3932 HighFrequencyr +
3933 LowFrequencyr) shr 1) /
3934 StreamOut[OutputIndex].Data.
3935 SampleRate);
3936 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
3937 1 / (1 + StreamOut[
3938 OutputIndex].DSP[
3939 FilterIndex].fftdata.Cr);
3940 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
3941 -StreamOut[OutputIndex].
3942 DSP[FilterIndex].fftdata.
3943 Dr *
3944 StreamOut[OutputIndex].
3945 DSP[FilterIndex].fftdata.
3946 a3r[0];
3947 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
3948 StreamOut[OutputIndex].
3949 DSP[FilterIndex].fftdata.
3950 a3r[0];
3951 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
3952 StreamOut[OutputIndex].
3953 DSP[FilterIndex].fftdata.
3954 a3r[1];
3955 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
3956 (1 - StreamOut[
3957 OutputIndex].DSP[
3958 FilterIndex].fftdata.Cr)
3959 *
3960 StreamOut[OutputIndex].
3961 DSP[FilterIndex].fftdata.
3962 a3r[0];
3963 // DSPFFTBandPass
3964 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2r :=
3965 1 / Tan (Pi * (
3966 HighFrequencyr
3967 - LowFrequencyr + 1) /
3968 StreamOut[OutputIndex].Data.
3969 SampleRate);
3970 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2r :=
3971 2 * Cos (2 * Pi * (roundmath
3972 (
3973 HighFrequencyr +
3974 LowFrequencyr) shr 1) /
3975 StreamOut[OutputIndex].Data.
3976 SampleRate);
3977 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[0] :=
3978 1 / (1 + StreamOut[
3979 OutputIndex].DSP[
3980 FilterIndex].fftdata.C2r
3981 );
3982 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
3983 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[2] :=
3984 -StreamOut[OutputIndex].
3985 DSP[FilterIndex].fftdata
3986 .a32r[0];
3987 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[0] :=
3988 -StreamOut[OutputIndex].
3989 DSP[FilterIndex].fftdata
3990 .C2r *
3991 StreamOut[OutputIndex].
3992 DSP[FilterIndex].fftdata
3993 .D2r *
3994 StreamOut[OutputIndex].
3995 DSP[FilterIndex].fftdata
3996 .a32r[0];
3997 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[1] :=
3998 (StreamOut[OutputIndex].
3999 DSP[FilterIndex].fftdata
4000 .C2r - 1) *
4001 StreamOut[OutputIndex].
4002 DSP[FilterIndex].fftdata
4003 .a32r[0];
4004 end;
4005
4006 2: // DSPFFTBandReject
4007 begin
4008 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
4009 Tan (Pi * (HighFrequencyr -
4010 LowFrequencyr + 1) /
4011 StreamOut[OutputIndex].Data.
4012 SampleRate);
4013 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr :=
4014 2 * Cos (2 * Pi * (roundmath
4015 (
4016 HighFrequencyr +
4017 LowFrequencyr) shr 1) /
4018 StreamOut[OutputIndex].Data.
4019 SampleRate);
4020 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
4021 1 / (1 + StreamOut[
4022 OutputIndex].DSP[
4023 FilterIndex].fftdata.Cr);
4024 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
4025 -StreamOut[OutputIndex].
4026 DSP[FilterIndex].fftdata.
4027 Dr *
4028 StreamOut[OutputIndex].
4029 DSP[FilterIndex].fftdata.
4030 a3r[0];
4031 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
4032 StreamOut[OutputIndex].
4033 DSP[FilterIndex].fftdata.
4034 a3r[0];
4035 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
4036 StreamOut[OutputIndex].
4037 DSP[FilterIndex].fftdata.
4038 a3r[1];
4039 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
4040 (1 - StreamOut[
4041 OutputIndex].DSP[
4042 FilterIndex].fftdata.Cr)
4043 *
4044 StreamOut[OutputIndex].
4045 DSP[FilterIndex].fftdata.
4046 a3r[0];
4047 end;
4048
4049 3: // DSPFFTBandPass
4050 begin
4051
4052 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
4053 1 / Tan (Pi * (HighFrequencyr
4054 -
4055 LowFrequencyr + 1) /
4056 StreamOut[OutputIndex].Data.
4057 SampleRate);
4058 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr :=
4059 2 * Cos (2 * Pi * (roundmath
4060 (
4061 HighFrequencyr +
4062 LowFrequencyr) shr 1) /
4063 StreamOut[OutputIndex].Data.
4064 SampleRate);
4065 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
4066 1 / (1 + StreamOut[
4067 OutputIndex].DSP[
4068 FilterIndex].fftdata.Cr);
4069 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
4070 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
4071 -StreamOut[OutputIndex].
4072 DSP[FilterIndex].fftdata.
4073 a3r[0];
4074 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
4075 -StreamOut[OutputIndex].
4076 DSP[FilterIndex].fftdata.
4077 Cr *
4078 StreamOut[OutputIndex].
4079 DSP[FilterIndex].fftdata.
4080 Dr *
4081 StreamOut[OutputIndex].
4082 DSP[FilterIndex].fftdata.
4083 a3r[0];
4084 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
4085 (StreamOut[OutputIndex].
4086 DSP[FilterIndex].fftdata.
4087 Cr - 1) *
4088 StreamOut[OutputIndex].
4089 DSP[FilterIndex].fftdata.
4090 a3r[0];
4091 end;
4092
4093 4: // DSPFFTLowPass
4094 begin
4095
4096 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
4097 1 / Tan (Pi * LowFrequencyr /
4098 StreamOut[OutputIndex].Data.
4099 SampleRate);
4100
4101 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
4102 1 / (1 + Sqrt (2) *
4103 StreamOut[OutputIndex].
4104 DSP[FilterIndex].fftdata.
4105 Cr +
4106 StreamOut[OutputIndex].
4107 DSP[FilterIndex].fftdata.
4108 Cr *
4109 StreamOut[OutputIndex].
4110 DSP[FilterIndex].fftdata.
4111 Cr);
4112 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
4113 2 * StreamOut[OutputIndex
4114 ].DSP[FilterIndex].
4115 fftdata.a3r[0];
4116 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
4117 StreamOut[OutputIndex].
4118 DSP[FilterIndex].fftdata.
4119 a3r[0];
4120 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
4121 2 * (1 - StreamOut[
4122 OutputIndex].DSP[
4123 FilterIndex].fftdata.Cr *
4124 StreamOut[OutputIndex].
4125 DSP[FilterIndex].fftdata.
4126 Cr) *
4127 StreamOut[OutputIndex].
4128 DSP[FilterIndex].fftdata.
4129 a3r[0];
4130 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
4131 (1 - Sqrt (2) * StreamOut
4132 [
4133 OutputIndex].DSP[
4134 FilterIndex].fftdata.Cr +
4135 StreamOut[OutputIndex].
4136 DSP[FilterIndex].fftdata.
4137 Cr *
4138 StreamOut[OutputIndex].
4139 DSP[FilterIndex].fftdata.
4140 Cr) *
4141 StreamOut[OutputIndex].
4142 DSP[FilterIndex].fftdata.
4143 a3r[0];
4144 end;
4145
4146 5: // DSPFFTHighPass
4147 begin
4148 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
4149 Tan (Pi * HighFrequencyr /
4150 StreamOut[OutputIndex].Data.
4151 SampleRate);
4152
4153 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
4154 1 / (1 + Sqrt (2) *
4155 StreamOut[OutputIndex].
4156 DSP[FilterIndex].fftdata.
4157 Cr +
4158 StreamOut[OutputIndex].
4159 DSP[FilterIndex].fftdata.
4160 Cr *
4161 StreamOut[OutputIndex].
4162 DSP[FilterIndex].fftdata.
4163 Cr);
4164 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
4165
4166 -2 * StreamOut[
4167 OutputIndex].DSP[
4168 FilterIndex].fftdata.a3r[
4169 0];
4170 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
4171 StreamOut[OutputIndex].
4172 DSP[FilterIndex].fftdata.
4173 a3r[0];
4174 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
4175 2 * (StreamOut[
4176 OutputIndex].DSP[
4177 FilterIndex].fftdata.Cr *
4178 StreamOut[OutputIndex].
4179 DSP[FilterIndex].fftdata.
4180 Cr - 1) *
4181 StreamOut[OutputIndex].
4182 DSP[FilterIndex].fftdata.
4183 a3r[0];
4184 StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
4185 (1 - Sqrt (2) * StreamOut
4186 [
4187 OutputIndex].DSP[
4188 FilterIndex].fftdata.Cr +
4189 StreamOut[OutputIndex].
4190 DSP[FilterIndex].fftdata.
4191 Cr *
4192 StreamOut[OutputIndex].
4193 DSP[FilterIndex].fftdata.
4194 Cr) *
4195 StreamOut[OutputIndex].
4196 DSP[FilterIndex].fftdata.
4197 a3r[0];
4198 end;
4199 end;
4200 end;
4201 end;
4202end;
4203
4204{$IF DEFINED (soundtouch)}
4205function SoundTouchPlug (bufferin: TDArFloat; plugHandle: THandle; notneeded :Tt_bs2bdp; Var
4206 inputData: Tuos_Data;
4207 notused1: float; notused2: float; notused3: float; notused4: float;
4208 notused5: float; notused6: float; notused7: float; notused8: float):TDArFloat;
4209var
4210 ratio : shortint;
4211 numoutbuf, x1, x2: cint32;
4212 BufferplugFLTMP: TDArFloat;
4213 BufferplugFL: TDArFloat;
4214begin
4215
4216 case inputData.LibOpen of
4217 0: ratio := 1;
4218 // sndfile
4219 1:
4220 begin
4221 // mpg123
4222 case inputData.SampleFormat of
4223 0: ratio := 2;
4224 // float32
4225 1: ratio := 2;
4226 // int32
4227 2: ratio := 1;
4228 // int16
4229 end;
4230 end;
4231 2: ratio := 1;
4232 3: ratio := 1;
4233 // cdrom
4234 4: ratio := 1;
4235 // opus
4236 5: ratio := 1;
4237 // xmp
4238 end;
4239
4240 if inputData.LibOpen <> 4 then//not working yet for opus files
4241 begin
4242 {$IF DEFINED (uos_debug) and DEFINED (unix)}
4243 writeln ();
4244 writeln ('_____Begin Sound touch_____');
4245 writeln ('soundtouch_putSamples: Length (bufferin) = ' + inttostr (length (bufferin)));
4246 writeln ('outframes = ' + inttostr (inputData.outframes)+
4247 ' ratio = ' + inttostr (ratio)+' channels = ' + inttostr (inputData.Channels));
4248 {$endif}
4249
4250 if inputData.outframes > 0 then
4251 begin
4252 soundtouch_putSamples (plugHandle, pcfloat (bufferin),
4253 inputData.outframes div cint (inputData.Channels * ratio));
4254
4255 {$IF DEFINED (uos_debug) and DEFINED (unix)}
4256 writeln ('inputData.outframes div trunc (inputData.Channels * ratio) = '
4257 + inttostr (inputData.outframes Div inputData.Channels * ratio));
4258 {$endif}
4259
4260 SetLength (BufferplugFL, 0);
4261 SetLength (BufferplugFLTMP, 0);
4262
4263 {$IF DEFINED (uos_debug) and DEFINED (unix)}
4264 writeln ('Length (BufferplugFL) = '
4265 + inttostr (Length (BufferplugFL)));
4266 writeln ('Length (Bufferin) = '
4267 + inttostr (Length (Bufferin)));
4268 writeln ('Length (BufferplugFLTMP) = '
4269 + inttostr (Length (BufferplugFLTMP)));
4270 {$endif}
4271
4272 SetLength (BufferplugFLTMP, (Length (Bufferin)));
4273
4274 {$IF DEFINED (uos_debug) and DEFINED (unix)}
4275 writeln ('2_Length (BufferplugFLTMP) = '
4276 + inttostr (Length (BufferplugFLTMP)));
4277 {$endif}
4278
4279 numoutbuf := 1;
4280
4281 while numoutbuf > 0 do
4282 begin
4283
4284 numoutbuf := soundtouch_receiveSamples (PlugHandle,
4285 pcfloat (BufferplugFLTMP), inputData.outframes);
4286
4287 {$IF DEFINED (uos_debug) and DEFINED (unix)}
4288 writeln ('numoutbuf = ' + inttostr (numoutbuf));
4289 {$endif}
4290
4291 if numoutbuf > 0 then
4292 begin
4293 {$IF DEFINED (uos_debug) and DEFINED (unix)}
4294 writeln ('SetLength (BufferplugFL) = ' + inttostr (length (BufferplugFL) +
4295 trunc(numoutbuf * inputData.Channels)));
4296 {$endif}
4297
4298 SetLength (BufferplugFL, length (BufferplugFL) + trunc (numoutbuf * inputData.
4299 Channels));
4300 // works only with 2 channels.
4301
4302 x2 := Length (BufferplugFL) - (numoutbuf * inputData.Channels);
4303
4304 for x1 := 0 to trunc (numoutbuf * inputData.Channels) -1 do
4305 begin
4306 BufferplugFL[x1 + x2] := BufferplugFLTMP[x1];
4307 end;
4308 end;
4309 end;
4310 end;
4311
4312 {$IF DEFINED (uos_debug) and DEFINED (unix)}
4313 writeln ('inputData.outframes = Length (BufferplugFL) = ' + inttostr (inputData.outframes));
4314 writeln ('_____End Sound touch_____');
4315 {$endif}
4316
4317 inputData.outframes := Length (BufferplugFL) Div inputData.Channels;
4318
4319 Result := BufferplugFL;
4320 end
4321 else
4322 begin
4323 SetLength (bufferin, inputData.outframes);
4324 Result := bufferin;
4325 end;
4326end;
4327
4328function GetBPMPlug (bufferin: TDArFloat; plugHandle: THandle; notneeded :Tt_bs2bdp; Var inputData:
4329 Tuos_Data;
4330 numframes: float; loop: float; notused3: float; notused4: float;
4331 notused5: float; notused6: float; notused7: float; notused8: float): TDArFloat;
4332var
4333 ratio : shortint;
4334begin
4335
4336 case inputData.LibOpen of
4337 0: ratio := 1;
4338 // sndfile
4339 1:
4340 begin
4341 // mpg123
4342 case inputData.SampleFormat of
4343 0: ratio := 2;
4344 // float32
4345 1: ratio := 2;
4346 // int32
4347 2: ratio := 1;
4348 // int16
4349 end;
4350 end;
4351 2: ratio := 1;
4352 3: ratio := 1;
4353 // cdrom
4354 4: ratio := 1;
4355 // opus
4356 5: ratio := 1;
4357 // xmp
4358 end;
4359
4360 if inputData.LibOpen <> 4 then//not working yet for opus files
4361 begin
4362 // writeln ('getBPM init ');
4363 if (theincbpm < numframes) and (theincbpm > -1) then
4364 begin
4365 bpm_putSamples (plugHandle, pcfloat (bufferin), length (bufferin) div inputData.channels);
4366 end
4367 else
4368 begin
4369 if theincbpm > -1 then
4370 begin
4371 inputData.BPM := bpm_getBpm (plugHandle);
4372 // writeln ('inputData.BPM := ' + floattostr (inputData.BPM));
4373 if loop = 1 then theincbpm := 0
4374 else theincbpm := -1;
4375
4376 end;
4377 end;
4378
4379 if theincbpm > -1 then inc (theincbpm);
4380
4381 SetLength (bufferin, inputData.outframes Div ratio);
4382 Result := bufferin;
4383 end;
4384end;
4385{$endif}
4386
4387{$IF DEFINED (bs2b)}
4388function bs2bPlug (bufferin: TDArFloat; notneeded: THandle; Abs2bd : Tt_bs2bdp; Var inputData: Tuos_Data;
4389 notused1: float; notused2: float; notused3: float; notused4: float;
4390 notused5: float; notused6: float; notused7: float; notused8: float): TDArFloat;
4391var
4392 x, x2: cint32;
4393 Bufferplug: TDArFloat;
4394begin
4395
4396 if (inputData.libopen = 0) or (inputData.libopen = 2) or (inputData.libopen = 3) or (inputData.
4397 libopen = 4) or (inputData.libopen = 5) then
4398 x2 := trunc (inputData.ratio * (inputData.outframes Div trunc (inputData.channels)));
4399
4400 if (inputData.libopen = 1) then
4401 begin
4402 if inputData.SampleFormat < 2 then
4403 x2 := trunc ((inputData.outframes Div trunc (inputData.channels)))
4404 else x2 := trunc (inputData.ratio * (inputData.outframes Div trunc (inputData.channels)));
4405 end;
4406
4407 SetLength (Bufferplug,x2);
4408
4409 x := 0;
4410
4411 while x < x2 do
4412 begin
4413
4414 Bufferplug[x] := bufferin[x];
4415 Bufferplug[x+1] := bufferin[x+1];
4416 bs2b_cross_feed_f (Abs2bd,Bufferplug[x],1);
4417 bs2b_cross_feed_f (Abs2bd,Bufferplug[x+1],2);
4418 x := x +2;
4419 end;
4420 Result := Bufferplug;
4421end;
4422{$endif}
4423
4424function Tuos_Player.AddPlugin(PlugName: Pchar; SampleRate: CDouble;
4425 Channels: cint32): cint32;
4426// SampleRate : default: -1 (44100)
4427// Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
4428// Result is PluginIndex
4429var
4430 x: cint32;
4431 chan, sr : integer;
4432begin
4433 x := -1;
4434 {$IF DEFINED (soundtouch)}
4435 if lowercase (PlugName) = 'soundtouch' then
4436 begin
4437 //
4438 SetLength (Plugin, Length (Plugin) + 1);
4439 x := Length (Plugin) - 1;
4440 Plugin[x] := Tuos_Plugin.Create ();
4441 Plugin[x].Enabled := false;
4442 Plugin[x].Name := lowercase (PlugName);
4443 Plugin[x].param1 := -1;
4444 Plugin[x].param2 := -1;
4445 Plugin[x].param3 := -1;
4446 Plugin[x].param4 := -1;
4447 Plugin[x].param5 := -1;
4448 Plugin[x].param6 := -1;
4449 Plugin[x].param7 := -1;
4450 Plugin[x].param8 := -1;
4451 Plugin[x].PlugHandle := soundtouch_createInstance ();
4452 if SampleRate = -1 then
4453 soundtouch_setSampleRate (Plugin[x].PlugHandle, 44100)
4454 else
4455 soundtouch_setSampleRate (Plugin[x].PlugHandle, roundmath (SampleRate));
4456 if Channels = -1 then
4457 soundtouch_setChannels (Plugin[x].PlugHandle, 2)
4458 else
4459 soundtouch_setChannels (Plugin[x].PlugHandle, Channels);
4460 soundtouch_setRate (Plugin[x].PlugHandle, 1);
4461 soundtouch_setTempo (Plugin[x].PlugHandle, 1);
4462 soundtouch_clear (Plugin[x].PlugHandle);
4463 Plugin[x].PlugFunc := @soundtouchplug;
4464 end;
4465
4466 if lowercase (PlugName) = 'getbpm' then
4467 begin
4468 SetLength (Plugin, Length (Plugin) + 1);
4469 x := Length (Plugin) - 1;
4470 Plugin[x] := Tuos_Plugin.Create ();
4471 Plugin[x].Enabled := true;
4472 Plugin[x].Name := lowercase (PlugName);
4473 Plugin[x].param1 := -1;
4474 Plugin[x].param2 := -1;
4475 Plugin[x].param3 := -1;
4476 Plugin[x].param4 := -1;
4477 Plugin[x].param5 := -1;
4478 Plugin[x].param6 := -1;
4479 Plugin[x].param7 := -1;
4480 Plugin[x].param8 := -1;
4481
4482 if SampleRate = -1 then
4483 sr := 44100
4484 else
4485 sr := roundmath (SampleRate);
4486 if Channels = -1 then
4487 chan := 2
4488 else
4489 chan := Channels;
4490
4491 Plugin[x].PlugHandle := bpm_createInstance (chan,sr);
4492
4493 Plugin[x].PlugFunc := @getbpmplug;
4494 end;
4495 {$endif}
4496
4497 {$IF DEFINED (bs2b)}
4498 if lowercase (PlugName) = 'bs2b' then
4499 begin
4500 SetLength (Plugin, Length (Plugin) + 1);
4501 Plugin[Length (Plugin) - 1] := Tuos_Plugin.Create ();
4502 x := Length (Plugin) - 1;
4503 Plugin[x].Name := lowercase (PlugName);
4504 Plugin[x].Enabled := true;
4505 if assigned (Plugin[x].Abs2b) then bs2b_close (Plugin[x].Abs2b);
4506 Plugin[x].Abs2b := bs2b_open ();
4507
4508 if SampleRate = -1 then
4509 bs2b_set_srate (Plugin[x].Abs2b, 44100)
4510 else
4511 bs2b_set_srate (Plugin[x].Abs2b, roundmath (SampleRate));
4512
4513 Plugin[x].param1 := -1;
4514 Plugin[x].param2 := -1;
4515 Plugin[x].param3 := -1;
4516 Plugin[x].param4 := -1;
4517 Plugin[x].param5 := -1;
4518 Plugin[x].param6 := -1;
4519 Plugin[x].param7 := -1;
4520 Plugin[x].param8 := -1;
4521 Plugin[x].PlugFunc := @bs2bplug;
4522 end;
4523 {$endif}
4524 Plugin[x].Enabled := true;
4525 Result := x;
4526end;
4527
4528{$IF DEFINED (soundtouch)}
4529procedure Tuos_Player.SetPluginSoundTouch (PluginIndex: cint32;
4530 Tempo: cfloat; Pitch: cfloat; Enable: boolean);
4531begin
4532 soundtouch_setRate (Plugin[PluginIndex].PlugHandle, Pitch);
4533 soundtouch_setTempo (Plugin[PluginIndex].PlugHandle, Tempo);
4534 Plugin[PluginIndex].Enabled := Enable;
4535 Plugin[PluginIndex].param1 := Tempo;
4536 Plugin[PluginIndex].param2 := Pitch;
4537end;
4538
4539procedure Tuos_Player.SetPluginGetBPM (PluginIndex: cint32; numofframes: integer; loop : boolean;
4540 Enable: boolean);
4541// PluginIndex : PluginIndex Index of an existing Plugin.
4542// numofframes: number of frames to analyse (-1 = 512 frames)
4543// loop: do new detection after previous.
4544begin
4545
4546 Plugin[PluginIndex].Enabled := Enable;
4547
4548 Plugin[PluginIndex].param1 := numofframes;
4549
4550 if (loop = true) then
4551 Plugin[PluginIndex].param2 := 1
4552 else Plugin[PluginIndex].param2 := 0;;
4553end;
4554{$endif}
4555
4556{$IF DEFINED (bs2b)}
4557procedure Tuos_Player.SetPluginBs2b (PluginIndex: cint32;
4558 level: CInt32; fcut: CInt32; feed: CInt32; Enable: boolean);
4559begin
4560
4561 Plugin[PluginIndex].Enabled := Enable;
4562
4563 if level > -1 then
4564 begin
4565 bs2b_set_level (Plugin[PluginIndex].Abs2b,level);
4566 Plugin[PluginIndex].param1 := level;
4567 end;
4568
4569 if fcut > -1 then
4570 begin
4571 bs2b_set_level_fcut (Plugin[PluginIndex].Abs2b,fcut);
4572 Plugin[PluginIndex].param2 := fcut;
4573 end;
4574
4575 if feed > -1 then
4576 begin
4577 bs2b_set_level_feed (Plugin[PluginIndex].Abs2b,feed);
4578 Plugin[PluginIndex].param3 := feed;
4579 end;
4580
4581end;
4582{$endif}
4583
4584function uos_InputGetLevelArray (PlayerIndex: cint32; InputIndex: cint32) : TDArFloat;
4585begin
4586 result := uosLevelArray[PlayerIndex][InputIndex];
4587end;
4588
4589{$IF DEFINED (noiseremoval)}
4590function uos_NoiseRemoval (Var Data: Tuos_Data; Var fft: Tuos_FFT): TDArFloat;
4591var
4592 ratio, x: cint32;
4593 Outfr : cint32;
4594 tempr : PSingle;
4595 pf: TDArFloat;
4596begin
4597
4598 case Data.LibOpen of
4599 0: ratio := 1;
4600 // sndfile
4601 1: ratio := 2;
4602 // mpg123
4603 2: ratio := 1;
4604 // aac
4605 3: ratio := 1;
4606 // cdrom
4607 4: ratio := 1;
4608 // opus
4609 5: ratio := 1;
4610 // xmp
4611 end;
4612
4613 if Data.SampleFormat = 0 then// TODO for Array of integer.
4614 begin
4615
4616 tempr := fft.FNoise.FilterNoise (pointer (Data.Buffer) ,
4617 (Data.OutFrames Div ratio) , Outfr);
4618
4619 setlength (pf,length (Data.Buffer));
4620
4621 for x := 0 to length (pf) -1 do
4622 begin
4623 if x < Outfr then
4624 pf[x] := tempr[x]
4625 else pf[x] := 0.0;
4626 end;
4627
4628 result := pf;
4629
4630 end
4631 else result := Data.Buffer;
4632 // TODO for Array of integer.
4633end;
4634 {$endif}
4635
4636function uos_DSPVolumeIn (Var Data: Tuos_Data;Var fft: Tuos_FFT): TDArFloat;
4637var
4638 x, ratio: cint32;
4639 vleft, vright: cfloat;
4640
4641 // volumearray : array of double;
4642
4643 ps: PDArShort;
4644 // if input is Int16 format
4645 pl: PDArLong;
4646 // if input is Int32 format
4647 pf: PDArFloat;
4648 // if input is Float32 format
4649begin
4650 //setlength (volumearray,Data.channels);
4651 vleft := Data.VLeft;
4652 vright := Data.VRight;
4653
4654 case Data.SampleFormat of
4655 2: // int16
4656 begin
4657 ps := @Data.Buffer;
4658 for x := 0 to (Data.OutFrames -1) do
4659 begin
4660 if (Data.VLeft <> 1) or (Data.Vright <> 1) then
4661 begin
4662 if odd (x) then
4663 ps^[x] := trunc (ps^[x] * vright)
4664 else
4665 ps^[x] := trunc (ps^[x] * vleft);
4666 end;
4667 // This to avoid distortion
4668 if ps^[x] < (-32760) then ps^[x] := -32760;
4669 if ps^[x] > (32760) then ps^[x] := 32760;
4670
4671 end;
4672
4673 end;
4674 1: // int32
4675 begin
4676 pl := @Data.Buffer;
4677 for x := 0 to (Data.OutFrames -1) do
4678 begin
4679 if (Data.VLeft <> 1) or (Data.Vright <> 1) then
4680 begin
4681 if odd (x) then
4682 pl^[x] := trunc (pl^[x] * vright)
4683 else
4684 pl^[x] := trunc (pl^[x] * vleft);
4685 end;
4686
4687 // This to avoid distortion
4688 if pl^[x] < (-2147000000) then pl^[x] := -2147000000;
4689 if pl^[x] > (2147000000) then pl^[x] := 2147000000;
4690
4691 end;
4692
4693 end;
4694 0: // float32
4695 begin
4696 case Data.LibOpen of
4697 0: ratio := 1;
4698 // sndfile
4699 1: ratio := 2;
4700 // mpg123
4701 2: ratio := 1;
4702 // aac
4703 3: ratio := 1;
4704 // cdrom
4705 4: ratio := 1;
4706 // opus
4707 5: ratio := 1;
4708 // xmp
4709 end;
4710
4711 pf := @Data.Buffer;
4712
4713 for x := 0 to (Data.OutFrames div ratio) -1 do
4714 begin
4715 if (Data.VLeft <> 1) or (Data.Vright <> 1) then
4716 begin
4717 if odd (x) then
4718 pf^[x] := pf^[x] * vright
4719 else
4720 pf^[x] := pf^[x] * vleft;
4721 end;
4722
4723 // This to avoid distortion
4724 if pf^[x] < -1 then pf^[x] := -1;
4725 if pf^[x] > 1 then pf^[x] := 1;
4726
4727 end;
4728
4729 end;
4730 end;
4731
4732 Result := Data.Buffer;
4733end;
4734
4735function uos_DSPVolumeOut (Var Data: Tuos_Data;Var fft: Tuos_FFT): TDArFloat;
4736var
4737 x: cint32;
4738 vleft, vright: cfloat;
4739 ps: PDArShort;
4740 // if output is Int16 format
4741 pl: PDArLong;
4742 // if output is Int32 format
4743 pf: PDArFloat;
4744 // if output is Float32 format
4745begin
4746 vleft := Data.VLeft;
4747 vright := Data.VRight;
4748
4749 case Data.SampleFormat of
4750 2: // int16
4751 begin
4752 ps := @Data.Buffer;
4753 for x := 0 to (length (Data.Buffer) -1) do
4754 begin
4755 if (Data.VLeft <> 1) or (Data.Vright <> 1) then
4756 begin
4757 if odd (x) then
4758 ps^[x] := trunc (ps^[x] * vright)
4759 else
4760 ps^[x] := trunc (ps^[x] * vleft);
4761 end;
4762 // This to avoid distortion
4763 if ps^[x] < (-32760) then ps^[x] := -32760;
4764 if ps^[x] > (32760) then ps^[x] := 32760;
4765
4766 end;
4767
4768 end;
4769 1: // int32
4770 begin
4771 pl := @Data.Buffer;
4772 for x := 0 to (length (Data.Buffer) -1) do
4773 begin
4774 if (Data.VLeft <> 1) or (Data.Vright <> 1) then
4775 begin
4776 if odd (x) then
4777 pl^[x] := trunc (pl^[x] * vright)
4778 else
4779 pl^[x] := trunc (pl^[x] * vleft);
4780 end;
4781
4782 // This to avoid distortion
4783 if pl^[x] < (-2147000000) then pl^[x] := -2147000000;
4784 if pl^[x] > (2147000000) then pl^[x] := 2147000000;
4785
4786 end;
4787 end;
4788 0: // float32
4789 begin
4790
4791 pf := @Data.Buffer;
4792
4793 for x := 0 to (length (Data.Buffer)) -1 do
4794 begin
4795 if (Data.VLeft <> 1) or (Data.Vright <> 1) then
4796 begin
4797 if odd (x) then
4798 pf^[x] := pf^[x] * vright
4799 else
4800 pf^[x] := pf^[x] * vleft;
4801 end;
4802
4803 // This to avoid distortion
4804 if pf^[x] < -1 then pf^[x] := -1;
4805 if pf^[x] > 1 then pf^[x] := 1;
4806
4807 end;
4808 end;
4809 end;
4810
4811 Result := Data.Buffer;
4812end;
4813
4814function Tuos_Player.DSPLevel (Data: Tuos_Data): Tuos_Data;
4815var
4816 x, ratio: cint32;
4817 ps: PDArShort;
4818 // if input is Int16 format
4819 pl: PDArLong;
4820 // if input is Int32 format
4821 pf: PDArFloat;
4822 // if input is Float32 format
4823 mins, maxs: array[0..1] of cInt16;
4824 // if input is Int16 format
4825 minl, maxl: array[0..1] of cInt32;
4826 // if input is Int32 format
4827 minf, maxf: array[0..1] of cfloat;
4828 // if input is Float32 format
4829begin
4830
4831 case Data.SampleFormat of
4832 2:
4833 begin
4834 mins[0] := 32767;
4835 mins[1] := 32767;
4836 maxs[0] := -32768;
4837 maxs[1] := -32768;
4838 ps := @Data.Buffer;
4839 x := 0;
4840 while x < Data.OutFrames -1 do
4841 begin
4842 if ps^[x] < mins[0] then
4843 mins[0] := ps^[x];
4844 if ps^[x] > maxs[0] then
4845 maxs[0] := ps^[x];
4846
4847 Inc (x, 1);
4848
4849 if ps^[x] < mins[1] then
4850 mins[1] := ps^[x];
4851 if ps^[x] > maxs[1] then
4852 maxs[1] := ps^[x];
4853
4854 Inc (x, 1);
4855 end;
4856
4857 if Abs (mins[0]) > Abs (maxs[0]) then
4858 Data.LevelLeft := Sqrt (Abs (mins[0]) / 32768)
4859 else
4860 Data.LevelLeft := Sqrt (Abs (maxs[0]) / 32768);
4861
4862 if Abs (mins[1]) > Abs (maxs[1]) then
4863 Data.Levelright := Sqrt (Abs (mins[1]) / 32768)
4864 else
4865 Data.Levelright := Sqrt (Abs (maxs[1]) / 32768);
4866
4867 end;
4868
4869 1:
4870 begin
4871 minl[0] := 2147483647;
4872 minl[1] := 2147483647;
4873 maxl[0] := -2147483648;
4874 maxl[1] := -2147483648;
4875 pl := @Data.Buffer;
4876 x := 0;
4877 while x < Data.OutFrames -1 do
4878 begin
4879 if pl^[x] < minl[0] then
4880 minl[0] := pl^[x];
4881 if pl^[x] > maxl[0] then
4882 maxl[0] := pl^[x];
4883
4884 Inc (x, 1);
4885
4886 if pl^[x] < minl[1] then
4887 minl[1] := pl^[x];
4888 if pl^[x] > maxl[1] then
4889 maxl[1] := pl^[x];
4890
4891 Inc (x, 1);
4892 end;
4893
4894 if Abs (minl[0]) > Abs (maxl[0]) then
4895 Data.LevelLeft := Sqrt (Abs (minl[0]) / 2147483648)
4896 else
4897 Data.LevelLeft := Sqrt (Abs (maxl[0]) / 2147483648);
4898
4899 if Abs (minl[1]) > Abs (maxl[1]) then
4900 Data.Levelright := Sqrt (Abs (minl[1]) / 2147483648)
4901 else
4902 Data.Levelright := Sqrt (Abs (maxl[1]) / 2147483648);
4903 end;
4904
4905 0:
4906 begin
4907 case Data.LibOpen of
4908 0: ratio := 1;
4909 // sndfile
4910 1: ratio := 2;
4911 // mpg123
4912 2: ratio := 2;
4913 // aac
4914 3: ratio := 2;
4915 // cdrom
4916 4: ratio := 2;
4917 // opus
4918 5: ratio := 1;
4919 // xmp
4920 end;
4921
4922 minf[0] := 1;
4923 minf[1] := 1;
4924 maxf[0] := -1;
4925 maxf[1] := -1;
4926 pf := @Data.Buffer;
4927 x := 0;
4928 while x < (Data.OutFrames div ratio)-1 do
4929 begin
4930 if pf^[x] < minf[0] then
4931 minf[0] := pf^[x];
4932 if pf^[x] > maxf[0] then
4933 maxf[0] := pf^[x];
4934
4935 Inc (x, 1);
4936
4937 if pf^[x] < minf[1] then
4938 minf[1] := pf^[x];
4939 if pf^[x] > maxf[1] then
4940 maxf[1] := pf^[x];
4941
4942 Inc (x, 1);
4943 end;
4944
4945 if Abs (minf[0]) > Abs (maxf[0]) then
4946 Data.LevelLeft := Sqrt (Abs (minf[0]))
4947 else
4948 Data.LevelLeft := Sqrt (Abs (maxf[0]));
4949
4950 if Abs (minf[1]) > Abs (maxf[1]) then
4951 Data.Levelright := Sqrt (Abs (minf[1]))
4952 else
4953 Data.Levelright := Sqrt (Abs (maxf[1]));
4954 end;
4955 end;
4956
4957 Result := Data;
4958end;
4959
4960function Tuos_Player.DSPLevelOut (Data: Tuos_Data): Tuos_Data;
4961var
4962 x, ratio: cint32;
4963 ps: PDArShort;
4964 // if input is Int16 format
4965 pl: PDArLong;
4966 // if input is Int32 format
4967 pf: PDArFloat;
4968 // if input is Float32 format
4969 mins, maxs: array[0..1] of cInt16;
4970 // if input is Int16 format
4971 minl, maxl: array[0..1] of cInt32;
4972 // if input is Int32 format
4973 minf, maxf: array[0..1] of cfloat;
4974 // if input is Float32 format
4975begin
4976
4977 case Data.SampleFormat of
4978 2:
4979 begin
4980 mins[0] := 32767;
4981 mins[1] := 32767;
4982 maxs[0] := -32768;
4983 maxs[1] := -32768;
4984 ps := @Data.Buffer;
4985 x := 0;
4986 while x < Data.OutFrames -1 do
4987 begin
4988 if ps^[x] < mins[0] then
4989 mins[0] := ps^[x];
4990 if ps^[x] > maxs[0] then
4991 maxs[0] := ps^[x];
4992
4993 Inc (x, 1);
4994
4995 if ps^[x] < mins[1] then
4996 mins[1] := ps^[x];
4997 if ps^[x] > maxs[1] then
4998 maxs[1] := ps^[x];
4999
5000 Inc (x, 1);
5001 end;
5002
5003 if Abs (mins[0]) > Abs (maxs[0]) then
5004 Data.LevelLeft := Sqrt (Abs (mins[0]) / 32768)
5005 else
5006 Data.LevelLeft := Sqrt (Abs (maxs[0]) / 32768);
5007
5008 if Abs (mins[1]) > Abs (maxs[1]) then
5009 Data.Levelright := Sqrt (Abs (mins[1]) / 32768)
5010 else
5011 Data.Levelright := Sqrt (Abs (maxs[1]) / 32768);
5012
5013 end;
5014
5015 1:
5016 begin
5017 minl[0] := 2147483647;
5018 minl[1] := 2147483647;
5019 maxl[0] := -2147483648;
5020 maxl[1] := -2147483648;
5021 pl := @Data.Buffer;
5022 x := 0;
5023 while x < Data.OutFrames -1 do
5024 begin
5025 if pl^[x] < minl[0] then
5026 minl[0] := pl^[x];
5027 if pl^[x] > maxl[0] then
5028 maxl[0] := pl^[x];
5029
5030 Inc (x, 1);
5031
5032 if pl^[x] < minl[1] then
5033 minl[1] := pl^[x];
5034 if pl^[x] > maxl[1] then
5035 maxl[1] := pl^[x];
5036
5037 Inc (x, 1);
5038 end;
5039
5040 if Abs (minl[0]) > Abs (maxl[0]) then
5041 Data.LevelLeft := Sqrt (Abs (minl[0]) / 2147483648)
5042 else
5043 Data.LevelLeft := Sqrt (Abs (maxl[0]) / 2147483648);
5044
5045 if Abs (minl[1]) > Abs (maxl[1]) then
5046 Data.Levelright := Sqrt (Abs (minl[1]) / 2147483648)
5047 else
5048 Data.Levelright := Sqrt (Abs (maxl[1]) / 2147483648);
5049 end;
5050
5051 0:
5052 begin
5053 ratio := 1;
5054
5055 minf[0] := 1;
5056 minf[1] := 1;
5057 maxf[0] := -1;
5058 maxf[1] := -1;
5059 pf := @Data.Buffer;
5060 x := 0;
5061 while x < (Data.OutFrames div ratio)-1 do
5062 begin
5063 if pf^[x] < minf[0] then
5064 minf[0] := pf^[x];
5065 if pf^[x] > maxf[0] then
5066 maxf[0] := pf^[x];
5067
5068 Inc (x, 1);
5069
5070 if pf^[x] < minf[1] then
5071 minf[1] := pf^[x];
5072 if pf^[x] > maxf[1] then
5073 maxf[1] := pf^[x];
5074
5075 Inc (x, 1);
5076 end;
5077
5078 if Abs (minf[0]) > Abs (maxf[0]) then
5079 Data.LevelLeft := Sqrt (Abs (minf[0]))
5080 else
5081 Data.LevelLeft := Sqrt (Abs (maxf[0]));
5082
5083 if Abs (minf[1]) > Abs (maxf[1]) then
5084 Data.Levelright := Sqrt (Abs (minf[1]))
5085 else
5086 Data.Levelright := Sqrt (Abs (maxf[1]));
5087 end;
5088 end;
5089
5090 Result := Data;
5091end;
5092
5093function DSPLevelString (Buffer: TDArFloat; SampleFormat, Ratio : cint32; Var resfloatleft : cfloat;
5094 Var resfloatright : cfloat): string;
5095var
5096 x, OutFrames: cint32;
5097 ps: PDArShort;
5098 // if input is Int16 format
5099 pl: PDArLong;
5100 // if input is Int32 format
5101 pf: PDArFloat;
5102 // if input is Float32 format
5103 mins, maxs: array[0..1] of cInt16;
5104 // if input is Int16 format
5105 minl, maxl: array[0..1] of cInt32;
5106 // if input is Int32 format
5107 minf, maxf: array[0..1] of cfloat;
5108 // if input is Float32 format
5109begin
5110
5111 OutFrames := length (buffer);
5112
5113 case SampleFormat of
5114 2:
5115 begin
5116 mins[0] := 32767;
5117 mins[1] := 32767;
5118 maxs[0] := -32768;
5119 maxs[1] := -32768;
5120 ps := @Buffer;
5121 x := 0;
5122 while x < OutFrames -1 do
5123 begin
5124 if ps^[x] < mins[0] then
5125 mins[0] := ps^[x];
5126 if ps^[x] > maxs[0] then
5127 maxs[0] := ps^[x];
5128
5129 Inc (x, 1);
5130
5131 if ps^[x] < mins[1] then
5132 mins[1] := ps^[x];
5133 if ps^[x] > maxs[1] then
5134 maxs[1] := ps^[x];
5135
5136 Inc (x, 1);
5137 end;
5138
5139 if Abs (mins[0]) > Abs (maxs[0]) then
5140 resfloatLeft := Sqrt (Abs (mins[0]) / 32768)
5141 else
5142 resfloatLeft := Sqrt (Abs (maxs[0]) / 32768);
5143
5144 if Abs (mins[1]) > Abs (maxs[1]) then
5145 resfloatright := Sqrt (Abs (mins[1]) / 32768)
5146 else
5147 resfloatright := Sqrt (Abs (maxs[1]) / 32768);
5148
5149 end;
5150
5151 1:
5152 begin
5153 minl[0] := 2147483647;
5154 minl[1] := 2147483647;
5155 maxl[0] := -2147483648;
5156 maxl[1] := -2147483648;
5157 pl := @Buffer;
5158 x := 0;
5159 while x < OutFrames -1 do
5160 begin
5161 if pl^[x] < minl[0] then
5162 minl[0] := pl^[x];
5163 if pl^[x] > maxl[0] then
5164 maxl[0] := pl^[x];
5165
5166 Inc (x, 1);
5167
5168 if pl^[x] < minl[1] then
5169 minl[1] := pl^[x];
5170 if pl^[x] > maxl[1] then
5171 maxl[1] := pl^[x];
5172
5173 Inc (x, 1);
5174 end;
5175
5176 if Abs (minl[0]) > Abs (maxl[0]) then
5177 resfloatLeft := Sqrt (Abs (minl[0]) / 2147483648)
5178 else
5179 resfloatLeft := Sqrt (Abs (maxl[0]) / 2147483648);
5180
5181 if Abs (minl[1]) > Abs (maxl[1]) then
5182 resfloatright := Sqrt (Abs (minl[1]) / 2147483648)
5183 else
5184 resfloatright := Sqrt (Abs (maxl[1]) / 2147483648);
5185 end;
5186
5187 0:
5188 begin
5189
5190 minf[0] := 1;
5191 minf[1] := 1;
5192 maxf[0] := -1;
5193 maxf[1] := -1;
5194 pf := @Buffer;
5195 x := 0;
5196 while x < (OutFrames div ratio) -1 do
5197 begin
5198 if pf^[x] < minf[0] then
5199 minf[0] := pf^[x];
5200 if pf^[x] > maxf[0] then
5201 maxf[0] := pf^[x];
5202
5203 Inc (x, 1);
5204
5205 if pf^[x] < minf[1] then
5206 minf[1] := pf^[x];
5207 if pf^[x] > maxf[1] then
5208 maxf[1] := pf^[x];
5209
5210 Inc (x, 1);
5211 end;
5212
5213 if Abs (minf[0]) > Abs (maxf[0]) then
5214 resfloatLeft := Sqrt (Abs (minf[0]))
5215 else
5216 resfloatLeft := Sqrt (Abs (maxf[0]));
5217
5218 if Abs (minf[1]) > Abs (maxf[1]) then
5219 resfloatright := Sqrt (Abs (minf[1]))
5220 else
5221 resfloatright := Sqrt (Abs (maxf[1]));
5222 end;
5223 end;
5224 Result := floattostr (resfloatleft) + '|' + floattostr (resfloatright);
5225end;
5226
5227
5228function uos_BandFilter (Var Data: Tuos_Data; Var fft: Tuos_FFT): TDArFloat;
5229var
5230 i, ratio: cint32;
5231 ifbuf: boolean;
5232 arg, res, res2: cfloat;
5233 ps, ps2: PDArShort;
5234 // if input is Int16 format
5235 pl, pl2: PDArLong;
5236 // if input is Int32 format
5237 pf, pf2: PDArFloat;
5238 // if input is Float32 format
5239begin
5240
5241 ratio := 1;
5242 ifbuf := fft.AlsoBuf;
5243
5244 case Data.SampleFormat of
5245 2:
5246 begin
5247 ps := @Data.Buffer;
5248 ps2 := @fft.VirtualBuffer;
5249 end;
5250 1:
5251 begin
5252 pl := @Data.Buffer;
5253 pl2 := @fft.VirtualBuffer;
5254 end;
5255 0:
5256 begin
5257 case Data.LibOpen of
5258 0: ratio := 1;
5259 // sndfile
5260 1: ratio := 2;
5261 // mpg123
5262 2: ratio := 2;
5263 // aac
5264 3: ratio := 2;
5265 // cdrom
5266 4: ratio := 2;
5267 // opus
5268 5: ratio := 1;
5269 // xmp
5270 end;
5271 pf := @Data.Buffer;
5272 pf2 := @fft.VirtualBuffer;
5273 end;
5274 end;
5275 i := 0;
5276 while i < (Data.OutFrames div ratio) -1 do
5277 begin
5278
5279 case Data.SampleFormat of
5280 2: arg := ps^[i];
5281 1: arg := pl^[i];
5282 0: arg := pf^[i];
5283 end;
5284
5285 res := fft.a3[0] * arg + fft.a3[1] * fft.x0[0] + fft.a3[2] *
5286 fft.x1[0] - fft.b2[0] * fft.y0[0] - fft.b2[1] * fft.y1[0];
5287
5288 if fft.typefilterL = 1 then
5289 begin
5290 res2 := fft.a32[0] * arg + fft.a32[1] * fft.x02[0] + fft.a32[2] *
5291 fft.x12[0] - fft.b22[0] * fft.y02[0] - fft.b22[1] * fft.y12[0];
5292
5293 case Data.SampleFormat of
5294 2:
5295 begin
5296 if ifbuf = True then
5297 ps^[i] := trunc ((res * 1) + (res2 * fft.gainl))
5298 else
5299 ps2^[i] := trunc ((res * 1) + (res2 * fft.gainl));
5300 end;
5301 1:
5302 begin
5303 if ifbuf = True then
5304 pl^[i] := trunc ((res * 1) + (res2 * fft.gainl))
5305 else
5306 pl2^[i] := trunc ((res * 1) + (res2 * fft.gainl));
5307 end;
5308 0:
5309 begin
5310
5311 if ifbuf = True then
5312 pf^[i] := ( (res * 1) + (res2 * fft.gainl))
5313 else
5314 pf2^[i] := ( (res * 1) + (res2 * fft.gainl));
5315 end;
5316 end;
5317
5318 end
5319 else
5320 case Data.SampleFormat of
5321 2:
5322 begin
5323
5324 if ifbuf = True then
5325 ps^[i] := trunc ((res * fft.gainl))
5326 else
5327 ps2^[i] := trunc (res * fft.gainl);
5328 end;
5329 1:
5330 begin
5331 if ifbuf = True then
5332 pl^[i] := trunc ((res * fft.gainl))
5333 else
5334 pl2^[i] := trunc (res * fft.gainl);
5335 end;
5336 0:
5337 begin
5338 if ifbuf = True then
5339 pf^[i] := ( (res * fft.gainl))
5340 else
5341 pf2^[i] := ( (res * fft.gainl));
5342 end;
5343 end;
5344
5345 fft.x1[0] := fft.x0[0];
5346 fft.x0[0] := arg;
5347 fft.y1[0] := fft.y0[0];
5348 fft.y0[0] := res;
5349
5350 if fft.typefilterL = 1 then
5351 begin
5352 fft.x12[0] := fft.x02[0];
5353 fft.x02[0] := arg;
5354 fft.y12[0] := fft.y02[0];
5355 fft.y02[0] := res2;
5356 end;
5357
5358 if Data.Channels = 2 then
5359 begin
5360 Inc (i);
5361 case Data.SampleFormat of
5362 2: arg := ps^[i];
5363 1: arg := pl^[i];
5364 0: arg := pf^[i];
5365 end;
5366 res := fft.a3r[0] * arg + fft.a3r[1] * fft.x0r[1] + fft.a3r[2] *
5367 fft.x1r[1] - fft.b2r[0] * fft.y0r[1] - fft.b2r[1] * fft.y1r[1];
5368
5369 if fft.typefilterR = 1 then
5370 begin
5371 res2 := fft.a32r[0] * arg + fft.a32r[1] * fft.x02r[1] +
5372 fft.a32r[2] * fft.x12r[1] - fft.b22r[0] * fft.y02r[1] -
5373 fft.b22r[1] * fft.y12r[1];
5374
5375 case Data.SampleFormat of
5376 2:
5377 begin
5378 if ifbuf = True then
5379 ps^[i] := trunc ((res * 1) + (res2 * fft.gainr))
5380 else
5381 ps2^[i] := trunc ((res * 1) + (res2 * fft.gainr));
5382 end;
5383 1:
5384 begin
5385 if ifbuf = True then
5386 pl^[i] := trunc ((res * 1) + (res2 * fft.gainr))
5387 else
5388 pl2^[i] := trunc ((res * 1) + (res2 * fft.gainr));
5389 end;
5390 0:
5391 begin
5392 if ifbuf = True then
5393 pf^[i] := ( (res * 1) + (res2 * fft.gainr))
5394 else
5395 pf2^[i] := ( (res * 1) + (res2 * fft.gainr));
5396 end;
5397 end;
5398
5399 end
5400 else
5401 case Data.SampleFormat of
5402 2:
5403 begin
5404 if ifbuf = True then
5405 ps^[i] := trunc ((res * fft.gainr))
5406 else
5407 ps2^[i] := trunc ((res * fft.gainr));
5408 end;
5409 1:
5410 begin
5411 if ifbuf = True then
5412 pl^[i] := trunc ((res * fft.gainr))
5413 else
5414 pl2^[i] := trunc ((res * fft.gainr));
5415 end;
5416 0:
5417 begin
5418 if ifbuf = True then
5419 pf^[i] := ( (res * fft.gainr))
5420 else
5421 pf2^[i] := ( (res * fft.gainr));
5422 end;
5423 end;
5424
5425 fft.x1r[1] := fft.x0r[1];
5426 fft.x0r[1] := arg;
5427 fft.y1r[1] := fft.y0r[1];
5428 fft.y0r[1] := res;
5429
5430 if fft.typefilterR = 1 then
5431 begin
5432 fft.x12r[1] := fft.x02r[1];
5433 fft.x02r[1] := arg;
5434 fft.y12r[1] := fft.y02r[1];
5435 fft.y02r[1] := res2;
5436 end;
5437
5438 end;
5439 Inc (i);
5440 end;
5441
5442 if ifbuf = false then
5443 begin
5444 data.levelfilters := data.levelfilters + '%'+ DSPLevelString (fft.VirtualBuffer, Data.
5445 SampleFormat, data.Ratio, data.levelleft, data.levelright);
5446 inc (Data.incfilters);
5447 Data.levelfiltersar[Data.incfilters-1] := data.levelleft;
5448 inc (Data.incfilters);
5449 Data.levelfiltersar[Data.incfilters-1] := data.levelright;
5450 end;
5451
5452 Result := Data.Buffer;
5453
5454end;
5455
5456function uos_InputAddDSP1ChanTo2Chan (Var Data: Tuos_Data; Var fft: Tuos_FFT): TDArFloat;
5457// Convert mono 1 chan input into stereo 2 channels input.
5458// Works only if the input is mono 1 channel othewise stereo 2 chan is keeped.
5459// InputIndex : InputIndex of an existing Input
5460// result : index of DSPIn in array
5461// example DSPIndex1 := InputAdd1ChanTo2Chan (InputIndex1);
5462var
5463 x, x2: integer;
5464
5465 ps, ps2: PDArShort;
5466 // if input is Int16 format
5467 pl, pl2: PDArLong;
5468 // if input is Int32 format
5469 pf, pf2: PDArFloat;
5470 // if input is Float32 format
5471
5472 buffer2 : TDArFloat;
5473
5474begin
5475 if (Data.channels = 1) then
5476 begin
5477 setlength (Buffer2, Data.OutFrames);
5478 x := 0;
5479 x2 := 0;
5480
5481 case Data.SampleFormat of
5482 2:
5483 begin
5484 ps := @Data.Buffer;
5485 ps2 := @Buffer2;
5486 while x < Data.OutFrames -1 do
5487 begin
5488 ps2^[x2] := (ps^[x]);
5489 ps2^[x2+1] := (ps^[x]);
5490 x := x + 1;
5491 x2 := x2 + 2;
5492 end;
5493 end;
5494
5495 1:
5496 begin
5497 pl := @Data.Buffer;
5498 pl2 := @Buffer2;
5499 while x < Data.OutFrames -1 do
5500 begin
5501 pl2^[x2] := (pl^[x]);
5502 pl2^[x2+1] := (pl^[x]);
5503 x := x + 1;
5504 x2 := x2 + 2;
5505 end;
5506 end;
5507
5508 0:
5509 begin
5510 pf := @Data.Buffer;
5511 pf2 := @Buffer2;
5512 while x < Data.OutFrames -1 do
5513 begin
5514 pf2^[x2] := (pf^[x]);
5515 pf2^[x2+1] := (pf^[x]);
5516 x := x + 1;
5517 x2 := x2 + 2;
5518 end;
5519 end;
5520 end;
5521 data.outframes := length (buffer2);
5522 Result := Buffer2;;
5523 end
5524 else
5525 begin
5526 Result := data.Buffer;
5527 end;
5528
5529end;
5530
5531function ConvertSampleFormat (Data: Tuos_Data): TDArFloat;
5532var
5533 x : integer;
5534
5535 ps, ps2: PDArShort;
5536 // if input is Int16 format
5537 pl, pl2: PDArLong;
5538 // if input is Int32 format
5539 buffer2 : TDArFloat;
5540
5541begin
5542 if (Data.SampleFormat > 0) then
5543 begin
5544 setlength (Buffer2, Data.OutFrames);
5545 x := 0;
5546
5547 case Data.SampleFormat of
5548 2:
5549 begin
5550 ps := @Data.Buffer;
5551 ps2 := @Buffer2;
5552 while x < Data.OutFrames do
5553 begin
5554 ps2^[x] := (ps^[x]);
5555 x := x + 1;
5556 end;
5557 end;
5558
5559 1:
5560 begin
5561 pl := @Data.Buffer;
5562 pl2 := @Buffer2;
5563 while x < Data.OutFrames do
5564 begin
5565 pl2^[x] := (pl^[x]);
5566 x := x + 1;
5567 end;
5568 end;
5569 end;
5570 Result := Buffer2;
5571 end
5572 else
5573 begin
5574 Result := data.Buffer;
5575 end;
5576
5577end;
5578
5579 {$IF DEFINED (noiseremoval)}
5580function Tuos_Player.InputAddDSPNoiseRemoval (InputIndex: cint32): cint32;
5581// DSP Noise Removal
5582// InputIndex : InputIndex of an existing Input
5583// result : otherwise index of DSPIn in array
5584// example DSPIndex1 := InputAddDSPNoiseRemoval (InputIndex1);
5585begin
5586
5587 Result := InputAddDSP (InputIndex, Nil, @uos_NoiseRemoval, Nil, Nil);
5588
5589 StreamIn[InputIndex].data.DSPNoiseIndex := Result;
5590
5591 StreamIn[InputIndex].DSP[result].fftdata := Tuos_FFT.Create ();
5592
5593 StreamIn[InputIndex].DSP[result].fftdata.FNoise :=
5594 TuosNoiseRemoval.Create (StreamIn[InputIndex].
5595 data.Channels,roundmath (StreamIn[InputIndex].
5596 data.
5597 SampleRate));
5598
5599 StreamIn[InputIndex].DSP[result].fftdata.FNoise.samprate :=
5600 roundmath (StreamIn[InputIndex].data.
5601 SampleRate);
5602
5603 StreamIn[InputIndex].DSP[result].fftdata.FNoise.WriteProc :=
5604 @StreamIn[InputIndex].DSP[result].
5605 fftdata.FNoise.WriteData;
5606
5607 StreamIn[InputIndex].DSP[result].fftdata.FNoise.isprofiled := false;
5608
5609end;
5610
5611procedure Tuos_Player.InputSetDSPNoiseRemoval (InputIndex: cint32; Enable: boolean);
5612
5613begin
5614 StreamIn[InputIndex].DSP[StreamIn[InputIndex].data.DSPNoiseIndex].enabled := Enable;
5615end;
5616
5617function Tuos_Player.OutputAddDSPNoiseRemoval (OutputIndex: cint32): cint32;
5618// DSP Noise Removal
5619// OutputIndex : OutputIndex of an existing Output
5620// result : otherwise index of DSPInOut in array
5621// example DSPIndex1 := OutputAddDSPNoiseRemoval (OutputIndex1);
5622begin
5623
5624 Result := OutputAddDSP (OutputIndex, Nil, @uos_NoiseRemoval, Nil, Nil);
5625
5626 StreamOut[OutputIndex].data.DSPNoiseIndex := Result;
5627
5628 StreamOut[OutputIndex].DSP[result].fftdata := Tuos_FFT.Create ();
5629
5630 StreamOut[OutputIndex].DSP[result].fftdata.FNoise :=
5631 TuosNoiseRemoval.Create (StreamOut[
5632 OutputIndex
5633 ].data.Channels,roundmath (StreamOut[
5634 OutputIndex].data.
5635 SampleRate));
5636
5637 StreamOut[OutputIndex].DSP[result].fftdata.FNoise.samprate :=
5638 roundmath (StreamOut[OutputIndex].
5639 data.
5640 SampleRate);
5641
5642 StreamOut[OutputIndex].DSP[result].fftdata.FNoise.WriteProc :=
5643 @StreamOut[OutputIndex].DSP[result]
5644 .fftdata.FNoise.WriteData;
5645
5646 StreamOut[OutputIndex].DSP[result].fftdata.FNoise.isprofiled := false;
5647
5648end;
5649
5650procedure Tuos_Player.OutputSetDSPNoiseRemoval (OutputIndex: cint32; Enable: boolean);
5651begin
5652 StreamOut[OutputIndex].DSP[StreamOut[OutputIndex].data.DSPNoiseIndex].enabled := Enable;
5653end;
5654
5655{$endif}
5656
5657function Tuos_Player.InputAddDSPVolume (InputIndex: cint32; VolLeft: double;
5658 VolRight: double): cint32;
5659// DSP Volume changer
5660// InputIndex : InputIndex of an existing Input
5661// VolLeft : Left volume
5662// VolRight : Right volume
5663// result : index of DSPIn in array
5664// example DSPIndex1 := InputAddDSPVolume (InputIndex1,1,1);
5665begin
5666 Result := InputAddDSP (InputIndex, Nil, @uos_DSPVolumeIn, Nil, Nil);
5667 StreamIn[InputIndex].Data.VLeft := VolLeft;
5668 StreamIn[InputIndex].Data.VRight := VolRight;
5669end;
5670
5671function Tuos_Player.InputAddDSP1ChanTo2Chan (InputIndex: cint32): cint32;
5672// Convert mono 1 channel input to stereo 2 channels input.
5673// Works only if the input is mono 1 channel othewise stereo 2 chan is keeped.
5674// InputIndex : InputIndex of an existing Input
5675// result : index of DSPIn in array
5676// example DSPIndex1 := InputAddDSP1ChanTo2Chan (InputIndex1);
5677begin
5678 Result := InputAddDSP (InputIndex, Nil, @uos_InputAddDSP1ChanTo2Chan, Nil, Nil);
5679end;
5680
5681function Tuos_Player.OutputAddDSPVolume (OutputIndex: cint32; VolLeft: double;
5682 VolRight: double): cint32;
5683// DSP Volume changer
5684// OutputIndex : OutputIndex of an existing Output
5685// VolLeft : Left volume ( 1 = max)
5686// VolRight : Right volume ( 1 = max)
5687// result : index of DSPIn in array
5688// example DSPIndex1 := OutputAddDSPVolume (OutputIndex1,1,1);
5689begin
5690 Result := OutputAddDSP (OutputIndex, Nil, @uos_DSPVolumeOut, Nil, Nil);
5691 StreamOut[OutputIndex].Data.VLeft := VolLeft;
5692 StreamOut[OutputIndex].Data.VRight := VolRight;
5693end;
5694
5695procedure Tuos_Player.InputSetDSPVolume (InputIndex: cint32; DSPVolIndex: cint32;
5696 VolLeft: double; VolRight: double; Enable: boolean);
5697// InputIndex : InputIndex of an existing Input
5698// DSPIndex : DSPVolIndex of an existing DSPVolume
5699// VolLeft : Left volume ( -1 = do not change)
5700// VolRight : Right volume ( -1 = do not change)
5701// Enable : Enabled
5702// example InputSetDSPVolume (InputIndex1,DSPVolIndex1,1,0.8,True);
5703begin
5704 if VolLeft <> -1 then
5705 StreamIn[InputIndex].Data.VLeft := VolLeft;
5706 if VolRight <> -1 then
5707 StreamIn[InputIndex].Data.VRight := VolRight;
5708 StreamIn[InputIndex].DSP[DSPVolIndex].Enabled := Enable;
5709end;
5710
5711procedure Tuos_Player.OutputSetDSPVolume (OutputIndex: cint32;
5712 DSPVolIndex: cint32; VolLeft: double; VolRight: double;
5713 Enable: boolean);
5714// OutputIndex : OutputIndex of an existing Output
5715// DSPIndex : DSPIndex of an existing DSP
5716// VolLeft : Left volume
5717// VolRight : Right volume
5718// Enable : Enabled
5719// example OutputSetDSPVolume (InputIndex1,DSPIndex1,1,0.8,True);
5720begin
5721 if VolLeft <> -1 then
5722 StreamOut[OutputIndex].Data.VLeft := VolLeft;
5723 if VolRight <> -1 then
5724 StreamOut[OutputIndex].Data.VRight := VolRight;
5725 StreamOut[OutputIndex].DSP[DSPVolIndex].Enabled := Enable;
5726end;
5727
5728function Tuos_Player.InputAddFilter (InputIndex: cint32;
5729 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
5730 cfloat;
5731 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
5732 cfloat;
5733 AlsoBuf: boolean; LoopProc: TProc): cint32;
5734// InputIndex : InputIndex of an existing Input
5735// TypeFilterL: Type of filter left:
5736// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
5737// LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
5738// HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
5739// GainL : gain left to apply to filter
5740// TypeFilterR: Type of filter right (ignored if mono):
5741// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
5742// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
5743// HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
5744// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
5745// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
5746// LoopProc : external procedure of object to synchronize after DSP done
5747// result : index of DSPIn in array
5748
5749var
5750 FilterIndex: cint32;
5751begin
5752 FilterIndex := InputAddDSP (InputIndex, Nil, @uos_BandFilter, Nil, LoopProc);
5753
5754 if alsobuf = false then
5755 begin
5756 StreamIn[InputIndex].data.hasfilters := true;
5757 inc (StreamIn[InputIndex].data.nbfilters);
5758 end;
5759
5760 StreamIn[InputIndex].DSP[FilterIndex].fftdata :=
5761 Tuos_FFT.Create ();
5762
5763 setlength (StreamIn[InputIndex].DSP[FilterIndex].fftdata.Virtualbuffer, length (StreamIn[
5764 InputIndex]
5765 .data.buffer));
5766
5767 if TypeFilterL = -1 then TypeFilterL := 1;
5768 if TypeFilterR = -1 then TypeFilterR := 1;
5769
5770 InputSetFilter (InputIndex, FilterIndex, TypeFilterL, LowFrequencyL, HighFrequencyL, GainL,
5771 TypeFilterR, LowFrequencyR, HighFrequencyR, GainR, AlsoBuf, LoopProc, True);
5772
5773 Result := FilterIndex;
5774end;
5775
5776function Tuos_Player.OutputAddFilter (OutputIndex: cint32;
5777 TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
5778 cfloat;
5779 TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
5780 cfloat;
5781 AlsoBuf: boolean; LoopProc: TProc): cint32;
5782// OutputIndex : InputIndex of an existing Output
5783// TypeFilterL: Type of filter left:
5784// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
5785// LowFrequencyL : Lowest frequency left ( -1 : current LowFrequency )
5786// HighFrequencyL : Highest frequency left ( -1 : current HighFrequency )
5787// GainL : gain left to apply to filter
5788// TypeFilterR: Type of filter right (ignored if mono):
5789// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
5790// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
5791// HighFrequencyR : Highest frequency left ( -1 : current HighFrequency )
5792// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
5793// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
5794// LoopProc : external procedure of object to synchronize after DSP done
5795// result : index of DSPIn in array
5796
5797var
5798 FilterIndex: cint32;
5799begin
5800 FilterIndex := OutputAddDSP (OutputIndex, Nil, @uos_BandFilter, Nil, LoopProc);
5801
5802 if alsobuf = false then
5803 begin
5804 StreamOut[OutputIndex].data.hasfilters := true;
5805 inc (StreamOut[OutputIndex].data.nbfilters);
5806 end;
5807
5808 StreamOut[OutputIndex].DSP[FilterIndex].fftdata :=
5809 Tuos_FFT.Create ();
5810
5811 setlength (StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Virtualbuffer,
5812 length (StreamOut[OutputIndex].data.buffer));
5813
5814 if TypeFilterL = -1 then TypeFilterL := 1;
5815 if TypeFilterR = -1 then TypeFilterR := 1;
5816
5817 OutputSetFilter (OutputIndex, FilterIndex, TypeFilterL, LowFrequencyL, HighFrequencyL, GainL,
5818 TypeFilterR, LowFrequencyR, HighFrequencyR, GainR, AlsoBuf, LoopProc, True);
5819
5820 Result := FilterIndex;
5821end;
5822
5823
5824{$IF DEFINED (portaudio)}
5825function Tuos_Player.AddFromDevIn (Device: cint32; Latency: CDouble;
5826 SampleRate: CDouble; OutputIndex: cint32;
5827 SampleFormat: cint32; FramesCount : cint32; ChunkCount: cint32): cint32;
5828// Add Input from IN device with custom parameters
5829// Device ( -1 is default Input device )
5830// Latency ( -1 is latency suggested )
5831// SampleRate : default: -1 (44100)
5832// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex
5833// (if multi-output then OutName = name of each output separated by ';')
5834// SampleFormat : -1 default: Int16 (0: Float32, 1:Int32, 2:Int16)
5835// FramesCount : -1 default: 4096
5836// ChunkCount : default: -1 (= 512)
5837var
5838 x, err: cint32;
5839begin
5840 result := -1;
5841
5842 if device = -1 then
5843 err := Pa_GetDefaultInputDevice ();
5844 if err = -1 then result := -2;
5845
5846 if result <> -2 then
5847 begin
5848 x := 0;
5849 err := -1;
5850 SetLength (StreamIn, Length (StreamIn) + 1);
5851 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create ();
5852 x := Length (StreamIn) - 1;
5853 StreamIn[x].Data.Enabled := false;
5854 StreamIn[x].Data.levelEnable := 0;
5855 StreamIn[x].Data.PositionEnable := 0;
5856 StreamIn[x].Data.levelArrayEnable := 0;
5857
5858 StreamIn[x].PAParam.HostApiSpecificStreamInfo := Nil;
5859
5860 if device = -1 then
5861 StreamIn[x].PAParam.device :=
5862 Pa_GetDefaultInputDevice ()
5863 else
5864 StreamIn[x].PAParam.device := cint32 (device);
5865
5866 if SampleRate = -1 then
5867 StreamIn[x].Data.SampleRate := DefRate
5868 else
5869 StreamIn[x].Data.SampleRate := SampleRate;
5870
5871 StreamIn[x].PAParam.SuggestedLatency := CDouble (0);
5872
5873 StreamIn[x].PAParam.SampleFormat := paInt16;
5874
5875 case SampleFormat of
5876 0: StreamIn[x].PAParam.SampleFormat := paFloat32;
5877 1: StreamIn[x].PAParam.SampleFormat := paInt32;
5878 2: StreamIn[x].PAParam.SampleFormat := paInt16;
5879 end;
5880
5881 if SampleFormat = -1 then
5882 StreamIn[x].Data.SampleFormat := CInt32 (2)
5883 else
5884 StreamIn[x].Data.SampleFormat := CInt32 (SampleFormat);
5885
5886 if ( (Pa_GetDeviceInfo (StreamIn[x].PAParam.device)^.
5887 maxInputChannels)) > 1 then
5888 StreamIn[x].PAParam.channelCount := CInt32 (2)
5889 else
5890 StreamIn[x].PAParam.channelCount := CInt32 (1);
5891
5892 StreamIn[x].data.channels := StreamIn[x].PAParam.channelCount;
5893
5894 if FramesCount = -1 then StreamIn[x].Data.Wantframes := 4096
5895 else
5896 StreamIn[x].Data.Wantframes := (FramesCount);
5897
5898 if ChunkCount = -1 then ChunkCount := 512;
5899
5900 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes* StreamIn[x].Data.channels);
5901
5902 StreamIn[x].Data.outframes := 0;
5903 StreamIn[x].Data.Status := 1;
5904 StreamIn[x].Data.TypePut := 1;
5905 StreamIn[x].Data.ratio := 2;
5906 StreamIn[x].Data.Output := OutputIndex;
5907 StreamIn[x].Data.seekable := False;
5908 StreamIn[x].Data.LibOpen := 2;
5909 StreamIn[x].LoopProc := Nil;
5910
5911 err := Pa_OpenStream (@StreamIn[x].Data.HandleSt, @StreamIn[x].PAParam,
5912 Nil, CDouble (StreamIn[x].Data.SampleRate), CULong (ChunkCount), paClipOff, Nil, Nil);
5913
5914 if err <> 0 then
5915 else
5916 begin
5917 StreamIn[x].Data.Enabled := True;
5918 Result := x;
5919 end;
5920 end
5921 else Result := -1;
5922end;
5923{$endif}
5924
5925function Tuos_Player.InputGetBuffer (InputIndex: cint32): TDArFloat;
5926// Get current buffer
5927begin
5928 result := StreamIn[InputIndex].data.Buffer;
5929end;
5930
5931function Tuos_Player.AddFromEndlessMuted (Channels : cint32; FramesCount: cint32): cint32;
5932// Add an input from Endless Muted dummy sine wav
5933// FramesCountByChan = FramesCount of input-to-follow div channels of input-to-follow.
5934var
5935 x, i : cint32;
5936begin
5937 result := -1;
5938 x := 0;
5939
5940 SetLength (StreamIn, Length (StreamIn) + 1);
5941 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create ();
5942 x := Length (StreamIn) - 1;
5943 StreamIn[x].Data.Enabled := false;
5944 StreamIn[x].Data.levelEnable := 0;
5945 StreamIn[x].Data.PositionEnable := 0;
5946 StreamIn[x].Data.levelArrayEnable := 0;
5947
5948 if channels = -1 then
5949 StreamIn[x].data.channels := 2
5950 else
5951 StreamIn[x].data.channels := Channels;
5952
5953 StreamIn[x].Data.SampleRate := DefRate;
5954
5955 if FramesCount = -1 then StreamIn[x].Data.Wantframes := trunc (1024 * 2 Div StreamIn[x].Data.
5956 channels)
5957 else
5958 StreamIn[x].Data.Wantframes := FramesCount * 2 Div channels ;
5959
5960 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes* StreamIn[x].Data.channels);
5961
5962 StreamIn[x].Data.OutFrames := StreamIn[x].Data.WantFrames;
5963
5964 for i := 0 to length (StreamIn[x].Data.Buffer) -1 do
5965 StreamIn[x].Data.Buffer[i] := 0.0;
5966
5967 StreamIn[x].Data.SampleFormat := CInt32 (0);
5968 StreamIn[x].Data.VLeft := 0;
5969 StreamIn[x].Data.Vright := 0;
5970 StreamIn[x].Data.Status := 1;
5971 StreamIn[x].Data.TypePut := 5;
5972 StreamIn[x].Data.HandleSt := pchar ('endless');
5973 StreamIn[x].Data.ratio := 2;
5974 StreamIn[x].Data.Output := -1;
5975 StreamIn[x].Data.seekable := False;
5976 StreamIn[x].Data.LibOpen := -1;
5977 StreamIn[x].LoopProc := Nil;
5978 StreamIn[x].Data.Enabled := True;
5979 Result := x;
5980end;
5981
5982{$IF DEFINED (synthesizer)}
5983function Tuos_Player.AddFromSynth (Channels: integer; WaveTypeL, WaveTypeR: shortint;
5984 FrequencyL, FrequencyR: float; VolumeL, VolumeR: float;
5985 duration : cint32; NbHarmonics: cint32; EvenHarmonics: cint32;
5986 OutputIndex: cint32; SampleFormat: cint32; SampleRate: CDouble;
5987 FramesCount : cint32): cint32;
5988// Add an input from Synthesizer with custom parameters
5989// Channels: default: -1 (2) (1 = mono, 2 = stereo)
5990// WaveTypeL: default: -1 (0) (0 = sine-wave 1 = square-wave, 2 = triangle, 2= triangle, 3=sawtooth used for mono and stereo)
5991// WaveTypeR: default: -1 (0) (0 = sine-wave 1 = square-wave,2 = triangle, 2= triangle, 3=sawtooth used, used for stereo, ignored for mono)
5992// FrequencyL: default: -1 (440 htz) (Left frequency, used for mono)
5993// FrequencyR: default: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
5994// VolumeL: default: -1 (= 1) (from 0 to 1) => volume left
5995// VolumeR: default: -1 (= 1) (from 0 to 1) => volume rigth (ignored for mono)
5996// Duration: default: -1 (= 1000) => duration in msec (0 = endless)
5997// NbHarmonics: default: -1 (= 0) Number of Harmonies
5998// EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
5999// OutputIndex: Output index of used output// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
6000// SampleFormat: default: -1 (0: Float32) (0: Float32, 1:Int32, 2:Int16)
6001// SampleRate: default: -1 (44100)
6002// FramesCount: -1 default: 1024
6003// result: Input Index in array -1 = error
6004
6005var
6006 x : cint32;
6007begin
6008 result := -1;
6009 x := 0;
6010
6011 SetLength (StreamIn, Length (StreamIn) + 1);
6012 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create ();
6013 x := Length (StreamIn) - 1;
6014 StreamIn[x].Data.Enabled := false;
6015 StreamIn[x].Data.levelEnable := 0;
6016 StreamIn[x].Data.PositionEnable := 0;
6017 StreamIn[x].Data.levelArrayEnable := 0;
6018
6019 if channels < 1 then
6020 StreamIn[x].data.channels := 2
6021 else
6022 StreamIn[x].data.channels := channels;
6023
6024 if SampleRate = -1 then
6025 StreamIn[x].Data.SampleRate := DefRate
6026 else
6027 StreamIn[x].Data.SampleRate := SampleRate;
6028
6029 if FramesCount = -1 then StreamIn[x].Data.Wantframes := 1024
6030 else
6031 StreamIn[x].Data.Wantframes := FramesCount;
6032
6033 if FrequencyL = -1 then
6034 StreamIn[x].Data.freqLsine := 440
6035 else
6036 StreamIn[x].Data.freqLsine := FrequencyL;
6037
6038 if FrequencyR = -1 then
6039 StreamIn[x].Data.freqRsine := 440
6040 else
6041 StreamIn[x].Data.freqRsine := FrequencyR;
6042
6043 if WaveTypeL < 1 then
6044 StreamIn[x].Data.typLsine := 0
6045 else
6046 StreamIn[x].Data.typLsine := WaveTypeL;
6047
6048 if WaveTypeR < 1 then
6049 StreamIn[x].Data.typRsine := 0
6050 else
6051 StreamIn[x].Data.typRsine := WaveTypeR;
6052
6053 StreamIn[x].Data.PosInTableLeft := 0;
6054 StreamIn[x].Data.PosInTableRight := 0;
6055
6056 if NbHarmonics < 1 then
6057 StreamIn[x].data.harmonic := 0
6058 else
6059 StreamIn[x].data.harmonic := NbHarmonics;
6060
6061 if EvenHarmonics < 1 then
6062 StreamIn[x].data.evenharm := 0
6063 else
6064 StreamIn[x].data.evenharm := 1;
6065
6066 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes* StreamIn[x].Data.channels);
6067
6068 StreamIn[x].Data.posdursine := 0;
6069
6070 if duration = -1 then duration := 1000;
6071 StreamIn[x].Data.dursine := trunc ( StreamIn[x].Data.SampleRate * duration / 1000);
6072
6073 if SampleFormat = -1 then
6074 StreamIn[x].Data.SampleFormat := CInt32 (0)
6075 else
6076 StreamIn[x].Data.SampleFormat := CInt32 (SampleFormat);
6077
6078 if VolumeL = -1 then StreamIn[x].Data.VLeft := 1
6079 else
6080 StreamIn[x].Data.VLeft := VolumeL;
6081
6082 if VolumeR = -1 then StreamIn[x].Data.Vright := 1
6083 else
6084 StreamIn[x].Data.Vright := VolumeR;
6085
6086 StreamIn[x].Data.Status := 1;
6087 StreamIn[x].Data.TypePut := 3;
6088 StreamIn[x].Data.HandleSt := pchar ('synth');
6089
6090 if (StreamIn[x].Data.SampleFormat = 2) then
6091 StreamIn[x].Data.ratio := StreamIn[x].data.channels
6092 else StreamIn[x].Data.ratio := 2;
6093
6094 StreamIn[x].Data.Output := OutputIndex;
6095 StreamIn[x].Data.seekable := False;
6096 StreamIn[x].Data.LibOpen := -1;
6097 StreamIn[x].LoopProc := Nil;
6098 StreamIn[x].Data.Enabled := True;
6099
6100 FillLookupTable (x, StreamIn[x].Data.typLsine, 1,StreamIn[x].data.harmonic, StreamIn[x].data.
6101 evenharm);
6102 FillLookupTable (x, StreamIn[x].Data.typRsine, 2,StreamIn[x].data.harmonic, StreamIn[x].data.
6103 evenharm);
6104
6105 Result := x;
6106end;
6107
6108procedure Tuos_Player.InputSetSynth (InputIndex: cint32; WaveTypeL, WaveTypeR: shortint;
6109 FrequencyL, FrequencyR: float; VolumeL, VolumeR: float;
6110 duration
6111 : cint32;
6112 NbHarmonic: cint32; EvenHarmonics: cint32; Enable: boolean);
6113// InputIndex: one existing input index
6114// WaveTypeL : do not change: -1 (0 = sine-wave 1 = square-wave, 2 = triangle, 2= triangle, 3=sawtooth used for mono and stereo)
6115// WaveTypeR : do not change: -1 (0 = sine-wave 1 = square-wave, 2 = triangle, 2= triangle, 3=sawtooth used for stereo, ignored for mono)
6116// FrequencyL : do not change: -1 (Left frequency, used for mono)
6117// FrequencyR : do not change: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
6118// VolumeL : do not change: -1 (= 1) (from 0 to 1) => volume left
6119// VolumeR : do not change: -1 (from 0 to 1) => volume rigth (ignored for mono)
6120// Duration : in msec (-1 = do not change)
6121// NbHarmonic : Number of Harmonies (-1 not change)
6122// EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
6123// Enable : true or false;
6124
6125var
6126 newtable : boolean = false;
6127begin
6128 StreamIn[InputIndex].Data.Enabled := Enable;
6129
6130 if NbHarmonic <> -1 then
6131 begin
6132 StreamIn[InputIndex].Data.harmonic := NbHarmonic;
6133 newtable := true;
6134 end;
6135
6136 if EvenHarmonics <> - 1 then
6137 begin
6138 if EvenHarmonics = 0 then
6139 StreamIn[InputIndex].data.evenharm := 0
6140 else
6141 StreamIn[InputIndex].data.evenharm := 1;
6142 newtable := true;
6143 end;
6144
6145 if WaveTypeL <> -1 then
6146 begin
6147 StreamIn[InputIndex].Data.typLsine := WaveTypeL;
6148 newtable := true;
6149 end;
6150
6151 if WaveTypeR <> -1 then
6152 begin
6153 StreamIn[InputIndex].Data.typRsine := WaveTypeR;
6154 newtable := true;
6155 end;
6156
6157 if FrequencyL <> -1 then
6158 begin
6159 StreamIn[InputIndex].Data.freqLsine := FrequencyL;
6160 end;
6161
6162 if FrequencyR <> -1 then
6163 begin
6164 StreamIn[InputIndex].Data.freqRsine := FrequencyR;
6165 end;
6166
6167 if VolumeL <> -1 then
6168 begin
6169 StreamIn[InputIndex].Data.VLeft := VolumeL;
6170 end;
6171
6172 if VolumeR <> -1 then
6173 begin
6174 StreamIn[InputIndex].Data.Vright := VolumeR;
6175 end;
6176
6177 if Duration <> -1 then StreamIn[InputIndex].Data.dursine :=
6178 trunc ( StreamIn[InputIndex].Data.
6179 SampleRate * duration / 1000);
6180
6181 if newtable then
6182 begin
6183 FillLookupTable (InputIndex,StreamIn[InputIndex].Data.typLsine, 1,
6184 StreamIn[InputIndex].Data.harmonic, StreamIn[InputIndex].data.evenharm);
6185 FillLookupTable (InputIndex,StreamIn[InputIndex].Data.typRsine, 2,
6186 StreamIn[InputIndex].Data.harmonic, StreamIn[InputIndex].data.evenharm);
6187 end;
6188
6189end;
6190{$endif}
6191
6192{$IF DEFINED (shout)}
6193function Tuos_Player.AddIntoIceServer (SampleRate : CDouble; Channels: cint; SampleFormat: cint;
6194 EncodeType: cint; Port: cint; Host: pchar; User: pchar;
6195 Password: pchar; MountFile :pchar): cint32;
6196// Add an Output into an IceCast server for audio-web-streaming
6197// SampleRate : default: -1 (48100)
6198// Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
6199// SampleFormat : -1 default: float32 : (0:float32, 1:Int16)
6200// EncodeType : default: -1 (0:Music) (0: Music, 1:Voice)
6201// Port : default: -1 (= 8000)
6202// Host : default: 'def' (= '127.0.0.1')
6203// User : default: 'def' (= 'source')
6204// Password : default: 'def' (= 'hackme')
6205// MountFile : default: 'def' (= '/example.opus')
6206// result : Output Index in array -1 = error
6207
6208var
6209 x, typeenc : cint32;
6210 err : integer = -1;
6211
6212begin
6213
6214 result := -1;
6215 x := 0;
6216 err := -1;
6217 SetLength (StreamOut, Length (StreamOut) + 1);
6218 StreamOut[Length (StreamOut) - 1] := Tuos_OutStream.Create ();
6219 x := Length (StreamOut) - 1;
6220
6221 StreamOut[x].Data.Enabled := false;
6222
6223 if (EncodeType = -1) or (EncodeType = 0) then typeenc := OPUS_APPLICATION_AUDIO
6224 else
6225 typeenc := OPUS_APPLICATION_VOIP;
6226
6227 if SampleRate = -1 then StreamOut[x].Data.SampleRate := 48000
6228 else
6229 StreamOut[x].Data.SampleRate := SampleRate;
6230
6231 if Channels = -1 then StreamOut[x].Data.Channels := 2
6232 else
6233 StreamOut[x].Data.Channels := Channels;
6234
6235 if SampleFormat = -1 then StreamOut[x].Data.SampleFormat := 0
6236 else
6237 StreamOut[x].Data.SampleFormat := SampleFormat;
6238
6239 StreamOut[x].Data.TypePut := 2;
6240
6241 setlength (StreamOut[x].Data.Buffer,1024 *2);
6242
6243 // setlength (StreamOut[x].Data.Buffer,960);
6244
6245 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6246 WriteLn ('before opus_encoder_create ' );
6247 {$endif}
6248
6249 // opus encoder
6250 StreamOut[x].encoder := opus_encoder_create (StreamOut[x].Data.SampleRate,
6251 StreamOut[x].Data.Channels, typeenc, err);
6252
6253 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6254 if (err<0)
6255 then
6256 begin
6257 WriteLn (Format ('failed to create an encoder: %s', [opus_strerror (err)]));
6258 end;
6259 {$endif}
6260 // if (err=0) then
6261 // err := opus_encoder_ctl (StreamOut[x].encoder , OPUS_SET_BITRATE (cBITRATE));
6262 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6263 if (err<0)
6264 then
6265 begin
6266 WriteLn (Format ('failed opus_encoder_ctl: %s', [opus_strerror (err)]));
6267 end;
6268 {$endif}
6269
6270 if err =0 then
6271 begin
6272
6273 StreamOut[x].Data.HandleSt := Nil;
6274
6275 shout_init ();
6276
6277 StreamOut[x].Data.HandleSt := shout_new ();
6278
6279 if assigned (StreamOut[x].Data.HandleSt) then
6280 begin
6281 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6282 WriteLn ('shhandle assigned');
6283 {$endif}
6284 err := shout_set_host ( StreamOut[x].Data.HandleSt, pchar (Host));
6285
6286 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6287 if err = SHOUTERR_SUCCESS then
6288 WriteLn ('shout_set_host ok ' + inttostr (err))
6289 else
6290 WriteLn ('shout_set_host error: ' + pchar (shout_get_error (StreamOut[x].Data.HandleSt))
6291 );
6292 {$endif}
6293 err := shout_set_protocol (StreamOut[x].Data.HandleSt, SHOUT_PROTOCOL_HTTP);
6294 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6295 if err = SHOUTERR_SUCCESS then
6296 WriteLn ('shout_set_protocol ' + inttostr (err))
6297 else
6298 WriteLn ('shout_set_protocol error: ' + pchar (shout_get_error (StreamOut[x].Data.
6299 HandleSt)
6300 ));
6301 {$endif}
6302 err := shout_set_port (StreamOut[x].Data.HandleSt, Port);
6303 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6304 if err = SHOUTERR_SUCCESS then
6305 WriteLn ('shout_set_port ok ' + inttostr (err))
6306 else
6307 WriteLn ('shout_set_port error: ' + pchar (shout_get_error (StreamOut[x].Data.HandleSt))
6308 );
6309 {$endif}
6310 err := shout_set_password (StreamOut[x].Data.HandleSt, pchar (Password));
6311 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6312 if err = SHOUTERR_SUCCESS then
6313 WriteLn ('set_password ok ' + inttostr (err))
6314 else
6315 WriteLn ('set_password error: ' + pchar (shout_get_error (StreamOut[x].Data.HandleSt)));
6316 {$endif}
6317 err := shout_set_mount (StreamOut[x].Data.HandleSt, pchar (MountFile));
6318 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6319 if err = SHOUTERR_SUCCESS then
6320 WriteLn ('shout_set_mount ok ' + inttostr (err))
6321 else
6322 WriteLn ('shout_set_mount error: ' + pchar (shout_get_error (StreamOut[x].Data.HandleSt)
6323 ));
6324 {$endif}
6325 err := shout_set_user (StreamOut[x].Data.HandleSt, pchar (user));
6326 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6327 if err = SHOUTERR_SUCCESS then
6328 WriteLn ('shout_set_user ok ' + inttostr (err))
6329 else
6330 WriteLn ('shout_set_user error: ' + pchar (shout_get_error (StreamOut[x].Data.HandleSt))
6331 );
6332 {$endif}
6333 err := shout_set_format (StreamOut[x].Data.HandleSt, SHOUT_FORMAT_OGG);
6334 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6335 if err = SHOUTERR_SUCCESS then
6336 WriteLn ('shout_set_format ok ' + inttostr (err))
6337 else
6338 WriteLn ('shout_set_format error: ' + pchar (shout_get_error (StreamOut[x].Data.HandleSt
6339 )))
6340 ;
6341 {$endif}
6342 err := shout_open (StreamOut[x].Data.HandleSt);
6343 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6344 if err = SHOUTERR_SUCCESS then
6345 WriteLn ('shout_open ok ' + inttostr (err))
6346 else
6347 WriteLn ('shout_open error: ' + pchar (shout_get_error (StreamOut[x].Data.HandleSt)));
6348 {$endif}
6349
6350 if err = SHOUTERR_SUCCESS then
6351 begin
6352 StreamOut[x].Data.Enabled := True;
6353 result := x
6354 end
6355 else
6356 begin
6357 shout_free (StreamOut[x].Data.HandleSt);
6358 StreamOut[Length (StreamOut) - 1].Destroy;
6359 setlength (StreamOut, Length (StreamOut) - 1);
6360 end;
6361 end
6362 else
6363 begin
6364 StreamOut[Length (StreamOut) - 1].Destroy;
6365 setlength (StreamOut, Length (StreamOut) - 1);
6366 {$IF DEFINED (uos_debug) and DEFINED (unix)}
6367 WriteLn ('shhandle not assigned') {$endif};
6368 end;
6369 end;
6370end;
6371 {$endif}
6372
6373procedure uos_CustBufferInfos (Var bufferinfos: Tuos_BufferInfos; SampleRate: CDouble; SampleFormat
6374 : cint32; Channels: cint32; Length: cint32);
6375begin
6376 bufferinfos.SampleRate := Samplerate;
6377 bufferinfos.SampleRateRoot := Samplerate;
6378 bufferinfos.SampleFormat := SampleFormat;
6379 bufferinfos.Channels := Channels;
6380 bufferinfos.Length := Length;
6381 bufferinfos.LibOpen := 0;
6382 bufferinfos.Ratio := 2;
6383end;
6384
6385
6386function Tuos_Player.AddIntoFileFromMem (Filenamepath: PChar; SampleRate: CDouble;
6387 Channels: LongInt; SampleFormat: LongInt; FramesCount:
6388 LongInt; FileFormat: cint32): LongInt;
6389// Add an Output into audio wav file with Custom parameters
6390// FileName : filename of saved audio wav file
6391// SampleRate : default: -1 (44100)
6392// Channels : default: -1 (2:stereo) (1:mono, 2:stereo, ...)
6393// SampleFormat : -1 default: Int16 : (1:Int32, 2:Int16)
6394// FramesCount : -1 default: 65536 div channels
6395// FileFormat : default: -1 (wav) (0:wav, 1:pcm, 2:custom);
6396// result : Output Index in array -1 = error
6397// example : OutputIndex1 := AddIntoFileFromMem (edit5.Text,-1,-1,0, -1);
6398var
6399 x: LongInt;
6400begin
6401 result := -1;
6402 x := 0;
6403 SetLength (StreamOut, Length (StreamOut) + 1);
6404 StreamOut[Length (StreamOut) - 1] := Tuos_OutStream.Create ();
6405 x := Length (StreamOut) - 1;
6406 StreamOut[x].Data.Enabled := false;
6407 StreamOut[x].FileBuffer.ERROR := 0;
6408 StreamOut[x].Data.Filename := Filenamepath;
6409 if (FileFormat = -1) or (FileFormat = 0) then
6410 StreamOut[x].FileBuffer.FileFormat := 0
6411 else StreamOut[x].FileBuffer.FileFormat := FileFormat;
6412 StreamOut[x].Data.TypePut := 4;
6413 FillChar (StreamOut[x].FileBuffer, sizeof (StreamOut[x].FileBuffer), 0);
6414 StreamOut[x].FileBuffer.DataMS := TMemoryStream.Create;
6415
6416 result := x;
6417
6418 if (Channels = -1) then
6419 StreamOut[x].FileBuffer.wChannels := 2
6420 else
6421 StreamOut[x].FileBuffer.wChannels := Channels;
6422
6423 StreamOut[x].Data.Channels := StreamOut[x].FileBuffer.wChannels;
6424
6425 if FramesCount = -1 then StreamOut[x].Data.Wantframes := 65536 Div StreamOut[x].Data.Channels
6426 else
6427 StreamOut[x].Data.Wantframes := FramesCount;
6428
6429 SetLength (StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
6430
6431 if (SampleFormat = -1) or (SampleFormat = 2) then
6432 begin
6433 StreamOut[x].FileBuffer.wBitsPerSample := 16;
6434 StreamOut[x].Data.SampleFormat := 2;
6435 end;
6436
6437 if (SampleFormat = 1) then
6438 begin
6439 StreamOut[x].FileBuffer.wBitsPerSample := 32;
6440 StreamOut[x].Data.SampleFormat := 1;
6441 end;
6442
6443 if SampleRate = -1 then
6444 StreamOut[x].FileBuffer.wSamplesPerSec := 44100
6445 else
6446 StreamOut[x].FileBuffer.wSamplesPerSec := roundmath (samplerate);
6447
6448 StreamOut[x].Data.Samplerate := StreamOut[x].FileBuffer.wSamplesPerSec;
6449 StreamOut[x].LoopProc := Nil;
6450 StreamOut[x].Data.Enabled := True;
6451end;
6452
6453function Tuos_Player.AddIntoFile (Filenamepath: PChar; SampleRate: CDouble;
6454 Channels: cint32; SampleFormat: cint32; FramesCount: cint32;
6455 FileFormat: cint32): cint32;
6456// Add an Output into audio wav file with custom parameters
6457// FileName : filename of saved audio wav file
6458// SampleRate : default: -1 (44100)
6459// Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
6460// SampleFormat : default: -1 (2:Int16) ( 1:Int32, 2:Int16)
6461// FramesCount : default: -1 (= 4096)
6462// FileFormat : default: -1 (wav) (0:wav, 1:pcm, 2:custom, 3:ogg);
6463// result : Output Index in array -1 = error
6464// example : OutputIndex1 := AddIntoFile (edit5.Text,-1,-1, 0, -1, -1);
6465var
6466 x: cint32;
6467 wChunkSize: cint32;
6468 wFileSize: cint32;
6469 IDwav: array[0..3] of char;
6470 Header: Tuos_WaveHeaderChunk;
6471 {$IF DEFINED (sndfile)}
6472 sfInfo: TSF_INFO;
6473 {$endif}
6474
6475begin
6476 result := -1;
6477 x := 0;
6478 SetLength (StreamOut, Length (StreamOut) + 1);
6479 StreamOut[Length (StreamOut) - 1] := Tuos_OutStream.Create ();
6480 x := Length (StreamOut) - 1;
6481 StreamOut[x].Data.Enabled := false;
6482 StreamOut[x].FileBuffer.ERROR := 0;
6483 StreamOut[x].Data.Filename := filenamepath;
6484 if (FileFormat = -1) or (FileFormat = 0) then
6485 StreamOut[x].FileBuffer.FileFormat := 0
6486 else StreamOut[x].FileBuffer.FileFormat := FileFormat;
6487
6488 FillChar (StreamOut[x].FileBuffer, sizeof (StreamOut[x].FileBuffer), 0);
6489
6490 result := x;
6491
6492 if (Channels = -1) then
6493 StreamOut[x].FileBuffer.wChannels := 2
6494 else
6495 StreamOut[x].FileBuffer.wChannels := Channels;
6496
6497 StreamOut[x].Data.Channels := StreamOut[x].FileBuffer.wChannels;
6498
6499 if FramesCount = -1 then StreamOut[x].Data.Wantframes := 65536 Div StreamOut[x].Data.Channels
6500 else
6501 StreamOut[x].Data.Wantframes := FramesCount;
6502
6503 SetLength (StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
6504
6505 if (SampleFormat = -1) or (SampleFormat = 2) then
6506 begin
6507 StreamOut[x].FileBuffer.wBitsPerSample := 16;
6508 StreamOut[x].Data.SampleFormat := 2;
6509 end;
6510
6511 if (SampleFormat = 1) then
6512 begin
6513 StreamOut[x].FileBuffer.wBitsPerSample := 32;
6514 StreamOut[x].Data.SampleFormat := 1;
6515 end;
6516
6517 if (SampleFormat = 0) then
6518 begin
6519 StreamOut[x].FileBuffer.wBitsPerSample := 32;
6520 StreamOut[x].Data.SampleFormat := 0;
6521 end;
6522
6523 if SampleRate = -1 then
6524 StreamOut[x].FileBuffer.wSamplesPerSec := 44100
6525 else
6526 StreamOut[x].FileBuffer.wSamplesPerSec := roundmath (samplerate);
6527
6528 StreamOut[x].Data.Samplerate := StreamOut[x].FileBuffer.wSamplesPerSec;
6529 StreamOut[x].LoopProc := Nil;
6530
6531 if fileformat = 3 then
6532 begin
6533 // ogg file
6534 {$IF DEFINED (sndfile)}
6535 StreamOut[x].FileBuffer.FileFormat := 3;
6536 StreamOut[x].Data.TypePut := 6;
6537 sfInfo.format := SF_FORMAT_OGG Or SF_FORMAT_VORBIS;
6538 sfInfo.channels := StreamOut[x].Data.Channels;
6539 sfInfo.frames := streamOut[x].Data.Wantframes;
6540 SFinfo.samplerate := StreamOut[x].FileBuffer.wSamplesPerSec;
6541 SFinfo.seekable := 0;
6542 StreamOut[x].Data.Enabled := True;
6543 StreamOut[x].Data.HandleSt := sf_open (pchar (FileNamepath), SFM_WRITE, sfInfo);
6544 {$endif}
6545 end
6546 else
6547 begin
6548 // wav file
6549 StreamOut[x].FileBuffer.Data := TFileStream.Create (filenamepath,fmCreate);
6550 StreamOut[x].FileBuffer.Data.Seek (0, soFromBeginning);
6551 StreamOut[x].Data.TypePut := 0;
6552 IDwav := 'RIFF';
6553 StreamOut[x].FileBuffer.Data.WriteBuffer (IDwav, 4);
6554 wFileSize := 0;
6555 StreamOut[x].FileBuffer.Data.WriteBuffer (wFileSize, 4);
6556 IDwav := 'WAVE';
6557 StreamOut[x].FileBuffer.Data.WriteBuffer (IDwav, 4);
6558 IDwav := 'fmt ';
6559 StreamOut[x].FileBuffer.Data.WriteBuffer (IDwav, 4);
6560 wChunkSize := SizeOf (Header);
6561 StreamOut[x].FileBuffer.Data.WriteBuffer (wChunkSize, 4);
6562
6563 case SampleFormat of
6564 0: Header.wFormatTag := 3;
6565 else Header.wFormatTag := 1;
6566 end;
6567
6568 //Header.wFormatTag := 1;
6569 Header.wChannels := StreamOut[x].FileBuffer.wChannels;
6570 Header.wSamplesPerSec := StreamOut[x].FileBuffer.wSamplesPerSec;
6571 Header.wBitsPerSample := StreamOut[x].FileBuffer.wBitsPerSample;
6572 Header.wBlockAlign := StreamOut[x].FileBuffer.wChannels * Header.wBitsPerSample Div 8;
6573 Header.wAvgBytesPerSec := StreamOut[x].FileBuffer.wSamplesPerSec * Header.wBlockAlign;
6574 Header.wcbSize := 0;
6575
6576 StreamOut[x].FileBuffer.Data.WriteBuffer (Header, SizeOf (Header));
6577 IDwav := 'data';
6578 StreamOut[x].FileBuffer.Data.WriteBuffer (IDwav, 4);
6579 wChunkSize := 0;
6580 StreamOut[x].FileBuffer.Data.WriteBuffer (wChunkSize, 4);
6581 StreamOut[x].Data.Enabled := True;
6582
6583 end;
6584end;
6585
6586function Tuos_Player.AddIntoMemoryBuffer (outmemory: PDArFloat): cint32;
6587// Add an Output into memory-bufffer
6588// outmemory : buffer to use to store memory buffer
6589// example : OutputIndex1 := AddIntoMemoryBuffer (bufmemory);
6590
6591var
6592 x: integer;
6593begin
6594 result := -1;
6595 x := 0;
6596 SetLength (StreamOut, Length (StreamOut) + 1);
6597 StreamOut[Length (StreamOut) - 1] := Tuos_OutStream.Create ();
6598 x := Length (StreamOut) - 1;
6599 StreamOut[x].Data.Enabled := false;
6600 StreamOut[x].Data.TypePut := 3;
6601 Streamout[x].Data.posmem := 0;
6602 Streamout[x].BufferOut := outmemory;
6603 StreamOut[x].Data.channels := 2;
6604 StreamOut[x].Data.Wantframes := 65536;
6605 StreamOut[x].Data.SampleFormat := 0;
6606 StreamOut[x].Data.SampleRate := 44100;
6607 SetLength (StreamOut[x].Data.Buffer,65536*2);
6608 intobuf := true;
6609 // to check, why ?
6610 result := x;
6611 StreamOut[x].Data.Enabled := True;
6612end;
6613
6614function Tuos_Player.AddIntoMemoryBuffer (outmemory: PDArFloat; SampleRate: CDouble; SampleFormat:
6615 LongInt;
6616 Channels: LongInt; FramesCount: LongInt): LongInt;
6617// Add an Output into Memory Buffer with parameters.
6618// outmemory : pointer of buffer to use to store memory.
6619// SampleRate : default: -1 (44100)
6620// SampleFormat : default: -1 (0:Float32) ( 1:Int32, 2:Int16)
6621// Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
6622// FramesCount : default: -1 (= 65536)
6623
6624var
6625 x, ch, sr, sf, fr: integer;
6626begin
6627 result := -1;
6628 x := 0;
6629 SetLength (StreamOut, Length (StreamOut) + 1);
6630 StreamOut[Length (StreamOut) - 1] := Tuos_OutStream.Create ();
6631 x := Length (StreamOut) - 1;
6632 StreamOut[x].Data.Enabled := false;
6633 StreamOut[x].Data.TypePut := 3;
6634 Streamout[x].Data.posmem := 0;
6635 Streamout[x].BufferOut := outmemory;
6636 if channels = -1 then ch := 2
6637 else ch := channels;
6638 StreamOut[x].Data.channels := ch;
6639 if SampleFormat = -1 then sf := 0
6640 else sf := SampleFormat;
6641 StreamOut[x].Data.SampleFormat := sf;
6642 if FramesCount = -1 then fr := 65536
6643 else fr := FramesCount;
6644 StreamOut[x].Data.Wantframes := fr;
6645 if SampleRate = -1 then sr := 44100
6646 else sr := roundmath (SampleRate);
6647 StreamOut[x].Data.SampleRate := sr;
6648
6649 SetLength (StreamOut[x].Data.Buffer,fr*ch);
6650 intobuf := true;
6651 // to check, why ?
6652 result := x;
6653 StreamOut[x].Data.Enabled := True;
6654end;
6655
6656 {$IF DEFINED (portaudio)}
6657function Tuos_Player.AddIntoDevOut (Device: cint32; Latency: CDouble;
6658 SampleRate: CDouble; Channels: cint32; SampleFormat: cint32;
6659 FramesCount: cint32; ChunkCount: cint32): cint32;
6660// Add an Output into Device Output
6661// Device ( -1 is default device )
6662// Latency ( -1 is latency suggested )
6663// SampleRate : default: -1 (44100)
6664// Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
6665// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
6666// FramesCount : default: -1 (= 65536)
6667// ChunkCount : default: -1 (= 512)
6668// result : Output Index in array -1 = error
6669// example : OutputIndex1 := AddIntoDevOut (-1,-1,-1,-1,0,-1,-1);
6670var
6671 x, x2, err: cint32;
6672
6673begin
6674 result := -1;
6675
6676 if device = -1 then
6677 err := Pa_GetDefaultOutputDevice ();
6678 if err = -1 then result := -2;
6679
6680 if result <> -2 then
6681 begin
6682 x := 0;
6683 err := -1;
6684 SetLength (StreamOut, Length (StreamOut) + 1);
6685 StreamOut[Length (StreamOut) - 1] := Tuos_OutStream.Create ();
6686 x := Length (StreamOut) - 1;
6687
6688 StreamOut[x].Data.Enabled := false;
6689 StreamOut[x].Data.levelEnable := 0;
6690 StreamOut[x].Data.levelArrayEnable := 0;
6691
6692 {$IF DEFINED (portaudio)}
6693 StreamOut[x].PAParam.hostApiSpecificStreamInfo := Nil;
6694 if device = -1 then
6695 StreamOut[x].PAParam.device := Pa_GetDefaultOutputDevice ()
6696 else
6697 StreamOut[x].PAParam.device := device;
6698 {$endif}
6699
6700 if SampleRate = -1 then
6701 StreamOut[x].Data.SampleRate := DefRate
6702 else
6703 StreamOut[x].Data.SampleRate := SampleRate;
6704
6705 {$IF DEFINED (portaudio)}
6706
6707 if Latency = -1 then
6708 StreamOut[x].PAParam.SuggestedLatency := CDouble ((Pa_GetDeviceInfo (StreamOut[x].PAParam
6709 .
6710 device)^. defaultHighOutputLatency)) * 1
6711 else StreamOut[x].PAParam.SuggestedLatency := CDouble (Latency);
6712
6713
6714 {$IF DEFINED (android)}
6715 StreamOut[x].PAParam.SampleFormat := paFloat32;
6716 {$else}
6717 StreamOut[x].PAParam.SampleFormat := paInt16;
6718 {$endif}
6719
6720 case SampleFormat of
6721 0: StreamOut[x].PAParam.SampleFormat := paFloat32;
6722 1: StreamOut[x].PAParam.SampleFormat := paInt32;
6723 2: StreamOut[x].PAParam.SampleFormat := paInt16;
6724 end;
6725 {$endif}
6726
6727 if SampleFormat = -1 then
6728 StreamOut[x].Data.SampleFormat := 2
6729 else
6730 StreamOut[x].Data.SampleFormat := SampleFormat;
6731
6732 if Channels = -1 then
6733 begin
6734 {$IF DEFINED (portaudio)}
6735 StreamOut[x].PAParam.channelCount := 2 ;
6736 {$endif}
6737 StreamOut[x].Data.Channels := 2 ;
6738 end
6739 else
6740 begin
6741 {$IF DEFINED (portaudio)}
6742 StreamOut[x].PAParam.channelCount := CInt32 (Channels);
6743 {$endif}
6744 StreamOut[x].Data.Channels := CInt32 (Channels);
6745 end;
6746
6747 if FramesCount = -1 then StreamOut[x].Data.Wantframes :=
6748
6749 {$IF DEFINED (android)}
6750 1024 * 64
6751 else
6752 {$else}
6753 65536 div StreamOut[x].Data.Channels
6754 else
6755 {$endif}
6756 StreamOut[x].Data.Wantframes := FramesCount;
6757
6758 if ChunkCount = -1 then ChunkCount := 512;
6759
6760 SetLength (StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
6761
6762 x2 := 0;
6763 while x2 < Length (StreamOut[x].Data.Buffer) do
6764 begin
6765 StreamOut[x].Data.Buffer[x2] := 0.0;
6766 inc (x2);
6767 end;
6768
6769 StreamOut[x].Data.TypePut := 1;
6770
6771 {$IF DEFINED (portaudio)}
6772 err := Pa_OpenStream (@StreamOut[x].Data.HandleSt, Nil, @StreamOut[x].PAParam, CDouble (
6773 StreamOut[x]
6774 .Data.SampleRate), CULong (ChunkCount), paClipOff, Nil, Nil);
6775// err := Pa_OpenDefaultStream (@StreamOut[x].Data.HandleSt, 2, 2, paFloat32, DefRate, 512, nil, nil);
6776 {$endif}
6777
6778 StreamOut[x].LoopProc := Nil;
6779 if err <> 0 then Result := -1
6780 else
6781 begin
6782 StreamOut[x].Data.Enabled := True;
6783 Result := x;
6784 end;
6785 end
6786 else Result := -1;
6787end;
6788
6789 {$endif}
6790
6791{$IF DEFINED (webstream)}
6792function Tuos_Player.AddFromURL(URL: PChar; OutputIndex: cint32;
6793 SampleFormat: cint32; FramesCount: cint32; AudioFormat: cint32;
6794 ICYon: boolean): cint32;
6795// Add an Input from Audio URL
6796// URL : URL of audio file
6797// OutputIndex : OutputIndex of existing Output// -1: all output, -2: no output, other cint32 : existing Output
6798// SampleFormat : -1 default: Int16 (0: Float32, 1:Int32, 2:Int16)
6799// FramesCount : default: -1 (4096)
6800// AudioFormat : default: -1 (auto-find) (0: mp3, 1: opus, 2:aac)
6801// ICYon : ICY data on/off
6802// example : InputIndex := AddFromURL ('http://someserver/somesound.mp3',-1,-1,-1,-1,-1, false);
6803var
6804 x, Err, len, len2, i: cint32;
6805 PipeBufferSize, totsamples: integer;
6806 buffadd: TBytes;
6807 samprat: cint32;
6808 {$IF DEFINED(mpg123)}
6809 mpinfo: Tmpg123_frameinfo;
6810 // BufferTag: array[1..128] of char;
6811 // F: file;
6812 // mpid3v2: Tmpg123_id3v2;
6813 {$ENDIF}
6814 {$IF DEFINED(opus)}
6815 s: UTF8string;
6816 j: integer;
6817 OpusTag: POpusTags;
6818 LComment: PPAnsiChar;
6819 LcommentLength: PInteger;
6820 {$ENDIF}
6821begin
6822 result := -1;
6823 x := 0;
6824 Err := -1;
6825
6826 SetLength(StreamIn, Length(StreamIn) + 1);
6827 StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create;
6828 x := Length(StreamIn) - 1;
6829
6830 StreamIn[x].Data.Enabled := false;
6831 StreamIn[x].Data.LibOpen := -1;
6832 StreamIn[x].Data.levelEnable := 0;
6833 StreamIn[x].Data.positionEnable := 0;
6834 StreamIn[x].Data.levelArrayEnable := 0;
6835
6836 if FramesCount = -1 then
6837 totsamples := 4096
6838 else
6839 totsamples := FramesCount;
6840
6841 PipeBufferSize := totsamples * SizeOf(single);
6842
6843 CreatePipeHandles(StreamIn[x].InHandle, StreamIn[x].OutHandle, PipeBufferSize);
6844 StreamIn[x].InPipe := TInputPipeStream.Create(StreamIn[x].InHandle);
6845 StreamIn[x].OutPipe := TOutputPipeStream.Create(StreamIn[x].OutHandle);
6846
6847 StreamIn[x].httpget := TThreadHttpGetter.Create(URL, StreamIn[x].OutPipe);
6848 StreamIn[x].httpget.FreeOnTerminate := true;
6849 StreamIn[x].httpget.ICYenabled := ICYon;
6850
6851 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6852 WriteLn('avant httpget.Start');
6853 {$ENDIF}
6854 StreamIn[x].httpget.Start;
6855
6856 i := 0;
6857 while (i < 100) and (StreamIn[x].httpget.IsRunning = false) do
6858 begin
6859 sleep(300);
6860 inc(i);
6861 end;
6862
6863 i := 0;
6864 while (i < 20) and (StreamIn[x].httpget.FormatType = 0) do
6865 begin
6866 sleep(300);
6867 inc(i);
6868 end;
6869
6870 if StreamIn[x].httpget.IsRunning = false then
6871 begin
6872 result := -1;
6873 StreamIn[x].httpget.Terminate;
6874 sleep(100);
6875 StreamIn[x].InPipe.Destroy;
6876 StreamIn[x].OutPipe.Destroy;
6877 end
6878 else
6879 begin
6880 {$IF DEFINED(fdkaac)}
6881 if ((StreamIn[x].httpget.FormatType = 3) and (AudioFormat = -1)) or (AudioFormat = 2) then
6882 begin
6883 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6884 WriteLn('Begin fdkaac');
6885 {$ENDIF}
6886 sleep(3000);
6887
6888 if StreamIn[x].httpget.IsRunning then
6889 begin
6890 StreamIn[x].Data.HandleSt := aacDecoder_Open(TRANSPORT_TYPE.TT_MP4_ADTS, 1);
6891 if StreamIn[x].Data.HandleSt = nil then
6892 begin
6893 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6894 WriteLn('NOT OK aacDecoder_Open ()');
6895 {$ENDIF}
6896 exit;
6897 end;
6898
6899 if aacDecoder_SetParam(StreamIn[x].Data.HandleSt, AAC_CONCEAL_METHOD, 1) <>
6900 AAC_DECODER_ERROR.AAC_DEC_OK then
6901 begin
6902 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6903 WriteLn('Unable to set the AAC_CONCEAL_METHOD');
6904 {$ENDIF}
6905 exit;
6906 end;
6907
6908 if aacDecoder_SetParam(StreamIn[x].Data.HandleSt, AAC_PCM_LIMITER_ENABLE, 0) <>
6909 AAC_DECODER_ERROR.AAC_DEC_OK then
6910 begin
6911 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6912 WriteLn('Unable to set the AAC_PCM_LIMITER_ENABLE');
6913 {$ENDIF}
6914 exit;
6915 end;
6916
6917 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6918 WriteLn('FIN INIT ------------- AACDecDecode');
6919 {$ENDIF}
6920
6921 StreamIn[x].Data.LibOpen := 2;
6922 if SampleFormat = -1 then
6923 StreamIn[x].Data.SampleFormat := 2
6924 else
6925 StreamIn[x].Data.SampleFormat := SampleFormat;
6926
6927 if FramesCount = -1 then
6928 StreamIn[x].Data.Wantframes := 65536
6929 else
6930 StreamIn[x].Data.Wantframes := FramesCount;
6931
6932 StreamIn[x].Data.Channels := 2;
6933 StreamIn[x].Data.Samplerate := 44100;
6934 StreamIn[x].Data.ratio := 2;
6935
6936 SetLength(StreamIn[x].Data.Buffer,
6937 StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels);
6938
6939 StreamIn[x].Data.Output := OutputIndex;
6940 StreamIn[x].Data.Status := 1;
6941 StreamIn[x].Data.Position := 0;
6942 StreamIn[x].Data.OutFrames := 0;
6943 StreamIn[x].Data.Poseek := 0;
6944 StreamIn[x].Data.TypePut := 2;
6945 StreamIn[x].Data.seekable := false;
6946 Err := 0;
6947 end
6948 else
6949 begin
6950 result := -1;
6951 StreamIn[x].httpget.Terminate;
6952 sleep(100);
6953 StreamIn[x].InPipe.Destroy;
6954 StreamIn[x].OutPipe.Destroy;
6955 end;
6956 end;
6957 {$ENDIF}
6958
6959 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6960 WriteLn('ac StreamIn[x].Data.LibOpen = ' + IntToStr(StreamIn[x].Data.LibOpen));
6961 {$ENDIF}
6962
6963 {$IF DEFINED(opus)}
6964 if ((StreamIn[x].httpget.FormatType = 2) and (AudioFormat = -1)) or (AudioFormat = 1) then
6965 begin
6966 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6967 WriteLn('Begin opus');
6968 {$ENDIF}
6969
6970 sleep(2000);
6971
6972 if StreamIn[x].httpget.IsRunning then
6973 begin
6974 len := 1;
6975 len2 := 0;
6976 SetLength(buffadd, PipeBufferSize);
6977 SetLength(StreamIn[x].Data.BufferTMP, PipeBufferSize);
6978
6979 while (len2 < PipeBufferSize) and (len > 0) do
6980 begin
6981 len := StreamIn[x].InPipe.Read(buffadd[0], PipeBufferSize - len2);
6982 if len > 0 then
6983 for i := 0 to len - 1 do
6984 StreamIn[x].Data.BufferTMP[i + len2] := buffadd[i];
6985 len2 := len2 + len;
6986 end;
6987
6988 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6989 WriteLn('PipeBufferSize = ' + IntToStr(PipeBufferSize));
6990 WriteLn('InPipe.Read = ' + IntToStr(len2));
6991 WriteLn('----------------------------------');
6992 {$ENDIF}
6993
6994 StreamIn[x].Data.HandleSt := PChar('opusurl');
6995 {$IF DEFINED(uos_debug) and DEFINED(unix)}
6996 WriteLn('StreamIn[x].Data.HandleSt url assisgned');
6997 {$ENDIF}
6998
6999 StreamIn[x].Data.HandleOP := op_test_callbacks(StreamIn[x].InPipe, uos_callbacks,
7000 StreamIn[x].Data.BufferTMP[0],
7001 PipeBufferSize, Err);
7002
7003 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7004 WriteLn('error: op_test_*: ' + IntToStr(Err));
7005 {$ENDIF}
7006
7007 if Err = 0 then
7008 begin
7009 Err := op_test_open(StreamIn[x].Data.HandleOP);
7010
7011 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7012 WriteLn('error: op_test_open: ' + IntToStr(Err));
7013 {$ENDIF}
7014
7015 if (Err = 0) and (op_link_count(StreamIn[x].Data.HandleOP) = 1) then
7016 begin
7017 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7018 WriteLn('OK open');
7019 {$ENDIF}
7020
7021 if SampleFormat = -1 then
7022 StreamIn[x].Data.SampleFormat := 2
7023 else
7024 StreamIn[x].Data.SampleFormat := SampleFormat;
7025
7026 // tag
7027 OpusTag := op_tags(StreamIn[x].Data.HandleOP, nil);
7028 if OpusTag <> nil then
7029 begin
7030 if OpusTag^.Comments > 0 then
7031 begin
7032 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7033 WriteLn(Format('OpusTag.comments = %d', [OpusTag^.Comments]));
7034 {$ENDIF}
7035 LComment := OpusTag^.user_comments;
7036 LcommentLength := OpusTag^.comment_lengths;
7037
7038 for j := 0 to OpusTag^.Comments - 1 do
7039 begin
7040 SetLength(s, LcommentLength^);
7041 Move(Pointer(LComment^)^, Pointer(s)^, LcommentLength^);
7042 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7043 WriteLn(s);
7044 {$ENDIF}
7045 if j = 1 then StreamIn[x].Data.Title := s;
7046 if j = 2 then StreamIn[x].Data.Artist := s;
7047 if j = 3 then StreamIn[x].Data.Album := s;
7048 if j = 4 then StreamIn[x].Data.Date := s;
7049 if j = 5 then StreamIn[x].Data.Comment := s;
7050 if j = 6 then StreamIn[x].Data.Tag := s;
7051 if j > 6 then
7052 StreamIn[x].Data.Comment := StreamIn[x].Data.Comment + ' ' + s;
7053 Inc(LComment);
7054 Inc(LcommentLength);
7055 end;
7056 end;
7057 end;
7058
7059 StreamIn[x].Data.Length := op_pcm_total(StreamIn[x].Data.HandleOP, nil);
7060 StreamIn[x].Data.Filename := URL;
7061 StreamIn[x].Data.Channels := op_channel_count(StreamIn[x].Data.HandleOP, nil);
7062
7063 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7064 WriteLn(Format('op_bitrate = %d', [op_bitrate(StreamIn[x].Data.HandleOP, nil)]));
7065 WriteLn('Length ' + IntToStr(StreamIn[x].Data.Length));
7066 WriteLn('Data.Channels ' + IntToStr(StreamIn[x].Data.Channels));
7067 {$ENDIF}
7068
7069 StreamIn[x].Data.Samplerate := 48000;
7070 StreamIn[x].Data.Samplerateroot := StreamIn[x].Data.Samplerate;
7071 StreamIn[x].Data.Wantframes := totsamples;
7072
7073 SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes);
7074
7075 StreamIn[x].Data.LibOpen := 4;
7076 StreamIn[x].Data.Status := 1;
7077 StreamIn[x].Data.Position := 0;
7078 StreamIn[x].Data.OutFrames := 0;
7079 StreamIn[x].Data.Poseek := -1;
7080 StreamIn[x].Data.TypePut := 2;
7081 StreamIn[x].Data.ratio := 1;
7082 StreamIn[x].Data.seekable := false;
7083 StreamIn[x].LoopProc := nil;
7084 StreamIn[x].Data.Enabled := true;
7085
7086 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7087 WriteLn('End opus');
7088 {$ENDIF}
7089 end;
7090 end;
7091 end
7092 else
7093 begin
7094 result := -1;
7095 StreamIn[x].httpget.Terminate;
7096 sleep(100);
7097 StreamIn[x].InPipe.Destroy;
7098 StreamIn[x].OutPipe.Destroy;
7099 end;
7100 end;
7101 {$ENDIF}
7102
7103 {$IF DEFINED(mpg123)}
7104 if ((StreamIn[x].httpget.FormatType = 1) and (AudioFormat = -1)) or (AudioFormat = 0) then
7105 begin
7106 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7107 WriteLn('Begin mpg123');
7108 {$ENDIF}
7109 sleep(500);
7110
7111 if StreamIn[x].httpget.IsRunning then
7112 begin
7113 if StreamIn[x].httpget.ICYenabled = true then
7114 CheckSynchronize(1500);
7115
7116 StreamIn[x].Data.HandleSt := mpg123_new(nil, Err);
7117
7118 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7119 if Err = 0 then
7120 WriteLn('===> mpg123_new => ok.')
7121 else
7122 WriteLn('===> mpg123_new NOT ok.');
7123 {$ENDIF}
7124
7125 if Err = 0 then
7126 begin
7127 if SampleFormat = -1 then
7128 StreamIn[x].Data.SampleFormat := 2
7129 else
7130 StreamIn[x].Data.SampleFormat := SampleFormat;
7131
7132 mpg123_format_none(StreamIn[x].Data.HandleSt);
7133 case StreamIn[x].Data.SampleFormat of
7134 0: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
7135 MPG123_ENC_FLOAT_32);
7136 1: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
7137 MPG123_ENC_SIGNED_32);
7138 2: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
7139 MPG123_ENC_SIGNED_16);
7140 end;
7141
7142 mpg123_replace_reader_handle(StreamIn[x].Data.HandleSt, @mpg_read_stream,
7143 @mpg_seek_url, nil);
7144
7145 if ICYon then
7146 mpg123_param(StreamIn[x].Data.HandleSt, MPG123_ICY_INTERVAL,
7147 StreamIn[x].httpget.IcyMetaInt, 0);
7148
7149 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7150 if ICYon then
7151 WriteLn('httpget.IcyMetaInt = ' + IntToStr(StreamIn[x].httpget.IcyMetaInt));
7152 if Err = 0 then
7153 WriteLn('===> mpg123_replace_reader_handle => ok.');
7154 {$ENDIF}
7155
7156 Err := mpg123_open_handle(StreamIn[x].Data.HandleSt, Pointer(StreamIn[x].InPipe));
7157
7158 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7159 if Err = 0 then
7160 WriteLn('===> mpg123_open_handle => ok.')
7161 else
7162 WriteLn('===> mpg123_open_handle => NOT ok.');
7163 {$ENDIF}
7164
7165 sleep(10);
7166 end;
7167
7168 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7169 if Err = 0 then
7170 WriteLn('===> mpg123_open_handle all => ok.')
7171 else
7172 WriteLn('===> mpg123_open_handle all => NOT ok.');
7173 {$ENDIF}
7174
7175 if Err = 0 then
7176 begin
7177 StreamIn[x].Data.Filename := URL;
7178 if FramesCount = -1 then
7179 StreamIn[x].Data.Wantframes := 1024
7180 else
7181 StreamIn[x].Data.Wantframes := FramesCount;
7182
7183 StreamIn[x].Data.Output := OutputIndex;
7184 StreamIn[x].Data.Status := 1;
7185 StreamIn[x].Data.Position := 0;
7186 StreamIn[x].Data.OutFrames := 0;
7187 StreamIn[x].Data.Poseek := -1;
7188 StreamIn[x].Data.TypePut := 2;
7189 StreamIn[x].Data.seekable := false;
7190 StreamIn[x].LoopProc := nil;
7191
7192 samprat := RoundMath(StreamIn[x].Data.Samplerate);
7193 Err := mpg123_getformat(StreamIn[x].Data.HandleSt, samprat,
7194 StreamIn[x].Data.Channels, StreamIn[x].Data.Encoding);
7195
7196 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7197 if Err = 0 then
7198 WriteLn('===> mpg123_getformat => ok.')
7199 else
7200 WriteLn('===> mpg123_getformat => NOT ok.');
7201 {$ENDIF}
7202
7203 if Err <> 0 then
7204 begin
7205 sleep(50);
7206 samprat := RoundMath(StreamIn[x].Data.Samplerate);
7207 Err := mpg123_getformat(StreamIn[x].Data.HandleSt, samprat,
7208 StreamIn[x].Data.Channels, StreamIn[x].Data.Encoding);
7209 end;
7210
7211 if Err = 0 then
7212 begin
7213 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7214 WriteLn('===> mpg123_getformat => ok');
7215 {$ENDIF}
7216
7217 SetLength(StreamIn[x].Data.Buffer,
7218 StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels);
7219
7220 StreamIn[x].Data.LibOpen := 1;
7221 if SampleFormat = -1 then
7222 StreamIn[x].Data.SampleFormat := 2
7223 else
7224 StreamIn[x].Data.SampleFormat := SampleFormat;
7225
7226 if StreamIn[x].Data.SampleFormat = 2 then
7227 StreamIn[x].Data.ratio := SizeOf(int16)
7228 else
7229 StreamIn[x].Data.ratio := SizeOf(int32);
7230
7231 mpg123_info(StreamIn[x].Data.HandleSt, mpinfo);
7232 StreamIn[x].Data.Samplerateroot := StreamIn[x].Data.Samplerate;
7233 StreamIn[x].Data.Hdformat := mpinfo.layer;
7234 StreamIn[x].Data.Frames := mpinfo.framesize;
7235 StreamIn[x].Data.Length := mpg123_length(StreamIn[x].Data.HandleSt);
7236
7237 if StreamIn[x].Data.SampleFormat = 0 then
7238 mpg123_param(StreamIn[x].Data.HandleSt, StreamIn[x].Data.Channels,
7239 MPG123_FORCE_FLOAT, 0);
7240
7241 StreamIn[x].Data.Enabled := true;
7242
7243 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7244 WriteLn('===> mpg123_infos end => ok');
7245 {$ENDIF}
7246 end;
7247 end;
7248 end
7249 else
7250 begin
7251 result := -1;
7252 StreamIn[x].httpget.Terminate;
7253 sleep(100);
7254 StreamIn[x].InPipe.Destroy;
7255 StreamIn[x].OutPipe.Destroy;
7256 end;
7257 end;
7258 {$ENDIF}
7259
7260 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7261 WriteLn('Before result ' + IntToStr(result));
7262 WriteLn('error ' + IntToStr(Err));
7263 WriteLn('StreamIn[x].Data.LibOpen ' + IntToStr(StreamIn[x].Data.LibOpen));
7264 WriteLn('Before Length (StreamIn) ' + IntToStr(Length(StreamIn)));
7265 {$ENDIF}
7266 sleep(10);
7267 if StreamIn[x].Data.LibOpen = -1 then
7268 begin
7269 if Err <> -133 then
7270 begin
7271 StreamIn[Length(StreamIn) - 1].Destroy;
7272 SetLength(StreamIn, Length(StreamIn) - 1);
7273 {$IF DEFINED(uos_debug) and DEFINED(unix)}
7274 WriteLn('After Length (StreamIn) ' + IntToStr(Length(StreamIn)));
7275 WriteLn('Result: ' + IntToStr(result));
7276 {$ENDIF}
7277 end;
7278 result := -1;
7279 end
7280 else
7281 begin
7282 StreamIn[x].Data.Enabled := true;
7283 result := x;
7284 end;
7285 end;
7286end;
7287
7288{$ENDIF}
7289
7290function Tuos_Player.AddFromMemoryBuffer(var MemoryBuffer: TDArFloat;
7291 var Bufferinfos: Tuos_bufferinfos; OutputIndex: cint32; FramesCount: cint32
7292 ): cint32;
7293// Add an input from memory buffer with custom parameters
7294// MemoryBuffer : the buffer
7295// Bufferinfos : infos of the buffer
7296// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')// Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)// SampleRate : default: -1 (44100)
7297// FramesCount : default: -1 (65536 div Channels)
7298// result : Input Index in array -1 = error
7299// example : InputIndex1 := AddFromMemoryBuffer (mybuffer, buffinfos,-1,1024);
7300
7301var
7302 x : cint32;
7303 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7304 st: string;
7305 i : cint32;
7306 {$endif}
7307begin
7308
7309 result := -1;
7310
7311 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7312 WriteLn ('AddFromMemoryBuffer Before all.');
7313 writeln ('length (MemoryBuffer) =' +inttostr (length (MemoryBuffer)));
7314 st := '';
7315 for i := 0 to length (MemoryBuffer) -1 do
7316 st := st + '|' + inttostr (i) + '=' + floattostr (MemoryBuffer[i]);
7317 WriteLn (st);
7318 {$endif}
7319
7320 // writeln ('length (MemoryBuffer) =' +inttostr (length (MemoryBuffer)));
7321
7322 SetLength (StreamIn, Length (StreamIn) + 1);
7323 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create;
7324 x := Length (StreamIn) - 1;
7325
7326 StreamIn[x].Data.Enabled := false;
7327 StreamIn[x].Data.levelEnable := 0;
7328 StreamIn[x].Data.typeput := 4;
7329 StreamIn[x].Data.positionEnable := 0;
7330 StreamIn[x].Data.levelArrayEnable := 0;
7331 StreamIn[x].Data.memorybuffer := MemoryBuffer;
7332
7333 sleep (50);
7334 //TODO: it is necessary?
7335
7336 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7337 WriteLn ('AddFromMemoryBuffer Before all.');
7338 writeln ('length (MemoryBuffer) =' +inttostr (length (MemoryBuffer)));
7339 st := '';
7340 for i := 0 to length (MemoryBuffer) -1 do
7341 st := st + '|' + inttostr (i) + '=' + floattostr (StreamIn[x].Data.memorybuffer[i]);
7342 WriteLn (st);
7343 {$endif}
7344
7345 StreamIn[x].Data.Length := length (MemoryBuffer);
7346 StreamIn[x].Data.LibOpen := 0;
7347
7348 StreamIn[x].Data.Channels := Bufferinfos.Channels;
7349
7350 if FramesCount = -1 then
7351 StreamIn[x].Data.Wantframes := 4096
7352 else
7353 StreamIn[x].Data.Wantframes := FramesCount;
7354
7355 StreamIn[x].Data.Samplerate := bufferinfos.SampleRate;
7356 StreamIn[x].Data.SampleRateRoot := Bufferinfos.Samplerate;
7357 StreamIn[x].Data.SampleFormat := Bufferinfos.SampleFormat;
7358 StreamIn[x].Data.Filename := BufferInfos.Filename;
7359 StreamIn[x].Data.Title := BufferInfos.Title;
7360 StreamIn[x].Data.Copyright := BufferInfos.Copyright;
7361 StreamIn[x].Data.Software := BufferInfos.Software;
7362 StreamIn[x].Data.Artist := BufferInfos.Artist;
7363 StreamIn[x].Data.Comment := BufferInfos.Comment;
7364 StreamIn[x].Data.Date := BufferInfos.Date;
7365 StreamIn[x].Data.Tag := BufferInfos.Tag;
7366 StreamIn[x].Data.track := BufferInfos.track;
7367 StreamIn[x].Data.Album := BufferInfos.Album;
7368 StreamIn[x].Data.Genre := BufferInfos.Genre;
7369 StreamIn[x].Data.HDFormat := BufferInfos.HDFormat;
7370 StreamIn[x].Data.Sections := BufferInfos.Sections;
7371 StreamIn[x].Data.Encoding := BufferInfos.Encoding;
7372 StreamIn[x].Data.bitrate := BufferInfos.bitrate;
7373 //StreamIn[x].Data.Length := BufferInfos.Length;
7374 StreamIn[x].Data.LibOpen := 0;
7375 StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
7376 StreamIn[x].Data.posmem := 0;
7377 StreamIn[x].Data.Output := OutputIndex;
7378 StreamIn[x].Data.Status := 1;
7379 StreamIn[x].Data.Position := 0;
7380 StreamIn[x].Data.OutFrames := 0;
7381 StreamIn[x].Data.Poseek := -1;
7382 StreamIn[x].Data.seekable := true;
7383 StreamIn[x].LoopProc := Nil;
7384 setlength (StreamIn[x].Data.buffer,StreamIn[x].Data.wantframes*StreamIn[x].Data.Channels);
7385 StreamIn[x].Data.Enabled := True;
7386 result := x;
7387end;
7388
7389function Tuos_Player.AddFromFileIntoMemory (Filename: Pchar; OutputIndex: cint32;
7390 SampleFormat: cint32; FramesCount: cint32; numbuf : cint): cint32;
7391// Add an input from audio file and store it into memory with custom parameters
7392// FileName : filename of audio file
7393// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
7394// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
7395// FramesCount : default: -1 (4096)
7396// result : Input Index in array -1 = error
7397// example : InputIndex1 := AddFromFileIntoMemory (edit5.Text,-1,0,-1);
7398var
7399 x, i : cint32;
7400 bufferinfos: Tuos_bufferinfos;
7401
7402 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7403 st: string;
7404 {$endif}
7405
7406begin
7407 result := -1;
7408
7409 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7410 WriteLn ('AddFromFileIntoMemory Before all.');
7411 {$endif}
7412
7413 if fileexists (filename) then
7414 begin
7415
7416 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7417 WriteLn ('Before setlength.');
7418 {$endif}
7419
7420 SetLength (StreamIn, Length (StreamIn) + 1);
7421 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create;
7422 x := Length (StreamIn) - 1;
7423 StreamIn[x].Data.Enabled := false;
7424 StreamIn[x].Data.levelEnable := 0;
7425 StreamIn[x].Data.typeput := 4;
7426 StreamIn[x].Data.lastbuf := 0;
7427 StreamIn[x].Data.positionEnable := 0;
7428 StreamIn[x].Data.levelArrayEnable := 0;
7429 // StreamIn[x].Data.wantframes := FramesCount;
7430
7431 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7432 writeln ('Before Filetobuffer');
7433 {$endif}
7434
7435 for i := 0 to length (tempoutmemory) -1 do
7436 tempoutmemory[i] := 0.0;
7437
7438 setlength (tempoutmemory, 0);
7439
7440 Filetobuffer (Filename, -1, SampleFormat, FramesCount, tempoutmemory, bufferinfos, -1, numbuf)
7441 ;
7442 sleep (50);
7443
7444 setlength (StreamIn[x].Data.memorybuffer, length (tempoutmemory));
7445 for i := 0 to length (tempoutmemory) -1 do
7446 StreamIn[x].Data.memorybuffer[i] := tempoutmemory [i];
7447
7448 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7449 writeln ('After Filetobuffer');
7450 writeln ('length (tempoutmemory) =' +inttostr (length (tempoutmemory)));
7451 st := '';
7452 for i := 0 to length (tempoutmemory) -1 do
7453 st := st + '|' + inttostr (i) + '=' + floattostr (tempoutmemory[i]);
7454 WriteLn ('OUTPUT DATA into portaudio------------------------------');
7455 WriteLn (st);
7456 {$endif}
7457
7458 StreamIn[x].Data.Length := tempLength;
7459 StreamIn[x].Data.Samplerate := tempSamplerate;
7460 StreamIn[x].Data.SampleFormat := tempSampleFormat;
7461 StreamIn[x].Data.LibOpen := tempLibOpen;
7462 StreamIn[x].Data.Channels := tempchan;
7463
7464 if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
7465 else
7466 StreamIn[x].Data.Wantframes := FramesCount;
7467
7468 StreamIn[x].Data.ratio := tempratio;
7469 StreamIn[x].Data.posmem := 0;
7470 StreamIn[x].Data.Output := OutputIndex;
7471 StreamIn[x].Data.Status := 1;
7472 StreamIn[x].Data.Position := 0;
7473 StreamIn[x].Data.OutFrames := 0;
7474 StreamIn[x].Data.Poseek := -1;
7475 StreamIn[x].Data.seekable := true;
7476 StreamIn[x].LoopProc := Nil;
7477 StreamIn[x].Data.Samplerate := bufferinfos.SampleRate;
7478 StreamIn[x].Data.SampleRateRoot := Bufferinfos.Samplerate;
7479 StreamIn[x].Data.SampleFormat := Bufferinfos.SampleFormat;
7480 StreamIn[x].Data.Filename := BufferInfos.Filename;
7481 StreamIn[x].Data.Title := BufferInfos.Title;
7482 StreamIn[x].Data.Copyright := BufferInfos.Copyright;
7483 StreamIn[x].Data.Software := BufferInfos.Software;
7484 StreamIn[x].Data.Artist := BufferInfos.Artist;
7485 StreamIn[x].Data.Comment := BufferInfos.Comment;
7486 StreamIn[x].Data.Date := BufferInfos.Date;
7487 StreamIn[x].Data.Tag := BufferInfos.Tag;
7488 StreamIn[x].Data.Album := BufferInfos.Album;
7489 StreamIn[x].Data.Genre := BufferInfos.Genre;
7490 StreamIn[x].Data.track := BufferInfos.track;
7491 StreamIn[x].Data.HDFormat := BufferInfos.HDFormat;
7492 StreamIn[x].Data.Sections := BufferInfos.Sections;
7493 StreamIn[x].Data.Encoding := BufferInfos.Encoding;
7494 StreamIn[x].Data.bitrate := BufferInfos.bitrate;
7495 StreamIn[x].Data.Length := BufferInfos.Length;
7496 StreamIn[x].Data.LibOpen := 0;
7497 StreamIn[x].Data.Ratio := 2;
7498
7499 setlength (StreamIn[x].Data.buffer,StreamIn[x].Data.wantframes*StreamIn[x].Data.Channels);
7500 StreamIn[x].Data.Enabled := True;
7501 result := x;
7502 end
7503 else result := -2;
7504
7505end;
7506
7507{$IF DEFINED (sndfile)}
7508function m_get_filelen (pms: PMemoryStream): tuos_count_t;
7509cdecl;
7510begin
7511 Result := pms^.Size;
7512end;
7513
7514function m_seek (offset: tuos_count_t; whence: cint32; pms: PMemoryStream): tuos_count_t;
7515cdecl;
7516const
7517 SEEK_SET = 0;
7518 SEEK_CUR = 1;
7519 SEEK_END = 2;
7520begin
7521 Result := 0;
7522 case whence of
7523 SEEK_SET: Result := pms^.Seek (offset, soFromBeginning);
7524 SEEK_CUR: Result := pms^.Seek (offset, soFromCurrent);
7525 SEEK_END: Result := pms^.Seek (offset, soFromEnd);
7526 end;
7527end;
7528
7529function m_read (Const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t;
7530cdecl;
7531
7532begin
7533 Result := pms^.Read (buf^,count);
7534end;
7535
7536function m_write (Const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t;
7537cdecl;
7538begin
7539 Result := pms^.Write (buf^,count);
7540end;
7541
7542function m_tell (pms: PMemoryStream): Tuos_count_t;
7543cdecl;
7544begin
7545 Result := pms^.Position;
7546end;
7547{$endif}
7548
7549function Tuos_Player.AddIntoMemoryStream(var MemoryStream: TMemoryStream;
7550 SampleRate: CDouble; SampleFormat: LongInt; Channels: LongInt;
7551 FramesCount: LongInt; AudioFormat: cint32): LongInt;
7552// Add an Output into TMemoryStream
7553// MemoryStream : the TMemoryStream to use to store memory.
7554// SampleRate : default: -1 (44100)
7555// SampleFormat : default: -1 (2:Int16) ( 1:Int32, 2:Int16)
7556// Channels : default: -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
7557// FramesCount : default: -1 (= 4096)
7558// AudioFormat : default: -1 (wav) (0:wav, 1:ogg);
7559
7560var
7561 x, ch, sr, sf, fr: integer;
7562 {$IF DEFINED (sndfile)}
7563 sfInfo: TSF_INFO;
7564 sfVirtual: TSF_VIRTUAL;
7565 {$endif}
7566
7567begin
7568 result := -1;
7569 x := 0;
7570 SetLength (StreamOut, Length (StreamOut) + 1);
7571 StreamOut[Length (StreamOut) - 1] := Tuos_OutStream.Create ();
7572 x := Length (StreamOut) - 1;
7573 StreamOut[x].Data.Enabled := false;
7574
7575 if channels = -1 then ch := 2
7576 else ch := channels;
7577 StreamOut[x].Data.channels := ch;
7578 if SampleFormat = -1 then sf := 2
7579 else sf := SampleFormat;
7580 StreamOut[x].Data.SampleFormat := sf;
7581 if FramesCount = -1 then fr := 4096
7582 else fr := FramesCount;
7583 StreamOut[x].Data.Wantframes := fr;
7584 if SampleRate = -1 then sr := 44100
7585 else sr := roundmath (SampleRate);
7586 StreamOut[x].Data.SampleRate := sr;
7587
7588 SetLength (StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
7589
7590 if MemoryStream = nil then
7591 MemoryStream := Tmemorystream.create;
7592
7593 Streamout[x].MemorySteamOut := MemoryStream;
7594
7595 Streamout[x].Data.posmem := 0;
7596
7597 StreamOut[x].Data.TypePut := 5;
7598
7599 {$IF DEFINED (sndfile)}
7600 with sfVirtual do
7601 begin
7602 sf_vio_get_filelen := @m_get_filelen;
7603 seek := @m_seek;
7604 read := @m_read;
7605 write := @m_write;
7606 tell := @m_tell;
7607 end;
7608
7609 if (AudioFormat = 0) then
7610 sfInfo.format := SF_FORMAT_WAV Or SF_FORMAT_PCM_16;
7611 if (AudioFormat = 1) then
7612 sfInfo.format := SF_FORMAT_OGG Or SF_FORMAT_VORBIS;
7613
7614 sfInfo.channels := StreamOut[x].Data.Channels;
7615 sfInfo.frames := streamOut[x].Data.Wantframes;
7616 SFinfo.samplerate := roundmath (StreamOut[x].Data.SampleRate);
7617 SFinfo.seekable := 0;
7618 StreamOut[x].Data.HandleSt := sf_open_virtual (@sfVirtual, SFM_WRITE, @sfInfo,
7619 @StreamOut[x].MemorySteamOut);
7620 {$endif}
7621 result := x;
7622 StreamOut[x].Data.Enabled := True;
7623end;
7624
7625function Tuos_Player.AddFromMemoryStreamDec(var MemoryStream: TMemoryStream;
7626 var Bufferinfos: Tuos_bufferinfos; OutputIndex: cint32; FramesCount: cint32
7627 ): cint32;
7628// MemoryStream : Memory-stream of decoded audio (like created by AddIntoMemoryStream)
7629// Bufferinfos : infos of the Memory-stream
7630// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
7631// FramesCount : default: -1 (4096)
7632// result : Input Index in array -1 = error
7633var
7634 x : integer;
7635begin
7636 result := -1;
7637
7638 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7639 WriteLn ('Before all.');
7640 {$endif}
7641
7642 if assigned (MemoryStream) then
7643 begin
7644 x := 0;
7645 MemoryStream.Position := 0;
7646
7647 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7648 WriteLn ('Before setlength.');
7649 {$endif}
7650
7651 SetLength (StreamIn, Length (StreamIn) + 1);
7652 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create;
7653 x := Length (StreamIn) - 1;
7654
7655 StreamIn[x].Data.LibOpen := -1;
7656 StreamIn[x].Data.levelEnable := 0;
7657 StreamIn[x].Data.Output := OutputIndex;
7658 StreamIn[x].Data.Status := 1;
7659 StreamIn[x].Data.Position := 0;
7660 StreamIn[x].Data.lastbuf := -1;
7661 StreamIn[x].Data.OutFrames := 0;
7662 StreamIn[x].Data.Poseek := -1;
7663 StreamIn[x].Data.TypePut := 6;
7664 StreamIn[x].Data.seekable := True;
7665 StreamIn[x].LoopProc := Nil;
7666 StreamIn[x].Data.Channels := Bufferinfos.Channels;
7667
7668 if FramesCount = -1 then
7669 StreamIn[x].Data.Wantframes := 4096
7670 else
7671 StreamIn[x].Data.Wantframes := FramesCount;
7672
7673 StreamIn[x].Data.Samplerate := bufferinfos.SampleRate;
7674 StreamIn[x].Data.SampleRateRoot := Bufferinfos.Samplerate;
7675 StreamIn[x].Data.SampleFormat := Bufferinfos.SampleFormat;
7676 StreamIn[x].Data.Filename := BufferInfos.Filename;
7677 StreamIn[x].Data.Title := BufferInfos.Title;
7678 StreamIn[x].Data.Copyright := BufferInfos.Copyright;
7679 StreamIn[x].Data.Software := BufferInfos.Software;
7680 StreamIn[x].Data.Artist := BufferInfos.Artist;
7681 StreamIn[x].Data.Comment := BufferInfos.Comment;
7682 StreamIn[x].Data.Date := BufferInfos.Date;
7683 StreamIn[x].Data.Tag := BufferInfos.Tag;
7684 StreamIn[x].Data.Album := BufferInfos.Album;
7685 StreamIn[x].Data.Track := BufferInfos.Track;
7686 StreamIn[x].Data.Genre := BufferInfos.Genre;
7687 StreamIn[x].Data.HDFormat := BufferInfos.HDFormat;
7688 StreamIn[x].Data.Sections := BufferInfos.Sections;
7689 StreamIn[x].Data.Encoding := BufferInfos.Encoding;
7690 StreamIn[x].Data.bitrate := BufferInfos.bitrate;
7691 //StreamIn[x].Data.Length := BufferInfos.Length;
7692 StreamIn[x].Data.LibOpen := -1;
7693 StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
7694 StreamIn[x].Data.posmem := 0;
7695 StreamIn[x].Data.Output := OutputIndex;
7696 StreamIn[x].Data.Status := 1;
7697 StreamIn[x].Data.Position := 0;
7698 StreamIn[x].Data.OutFrames := 0;
7699 StreamIn[x].Data.Poseek := -1;
7700 StreamIn[x].Data.seekable := false;
7701 StreamIn[x].LoopProc := Nil;
7702 streamIn[x].Data.ratio := StreamIn[x].Data.Channels;
7703 StreamIn[x].Data.positionEnable := 0;
7704 StreamIn[x].Data.levelArrayEnable := 0;
7705 StreamIn[x].MemoryStreamDec := MemoryStream;
7706 StreamIn[x].MemoryStreamDec.Position := 0;
7707 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.Channels);
7708 StreamIn[x].Data.Enabled := true;
7709
7710 result := x;
7711 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7712 writeln ('length (StreamIn[x].MemoryStreamDec) = '+inttostr (StreamIn[x].MemoryStreamDec.size)
7713 );
7714 writeln ('length (MemoryStream) = '+inttostr (MemoryStream.size));
7715 WriteLn ('Length (StreamIn) = '+ inttostr (x));
7716 {$endif}
7717 end
7718 else result := -1;
7719
7720end;
7721
7722// MemoryStream : Memory stream of encoded audio file.
7723// TypeAudio : default: -1 --> 0 (0: flac, ogg, wav; 1: mp3; 2:opus; 3:decoded Tmemory-stream; 5:mod, it, xm, s3m)
7724// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to an existing OutputIndex (if multi-output then OutName = name of each output separated by ';')
7725// SampleFormat : default: -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
7726// FramesCount : default: -1 (4096)
7727// result : Input Index in array -1 = error
7728// example : InputIndex1 := AddFromMemoryStream (mymemorystream,-1,-1,0,1024);
7729function Tuos_Player.AddFromMemoryStream(var MemoryStream: TMemoryStream;
7730 TypeAudio: cint32; OutputIndex: cint32; SampleFormat: cint32;
7731 FramesCount: cint32): cint32;
7732var
7733 x, x2, err, len, len2, i : cint32;
7734 PipeBufferSize, totsamples : integer;
7735 buffadd : tbytes;
7736 samprat : cint32;
7737
7738 {$IF DEFINED (sndfile)}
7739 sfInfo: TSF_INFO;
7740 sfVirtual: TSF_VIRTUAL;
7741 {$endif}
7742
7743 {$IF DEFINED (opus)}
7744 s: UTF8String;
7745 j: Integer;
7746 OpusTag: POpusTags;
7747 LComment: PPAnsiChar;
7748 LcommentLength: PInteger;
7749 {$endif}
7750
7751 {$IF DEFINED (mpg123)}
7752 mpinfo: Tmpg123_frameinfo;
7753 // problems with mpg123
7754 mpid3v1: PPmpg123_id3v1;
7755 refmpid3v1: Tmpg123_id3v1;
7756 mpid3v2: Tmpg123_id3v2;
7757 {$endif}
7758
7759 {$IF DEFINED (xmp)}
7760 mi: xmp_module_info;
7761 {$endif}
7762
7763begin
7764 result := -1;
7765
7766 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7767 WriteLn ('Before all.');
7768 {$endif}
7769
7770 if assigned (MemoryStream) then
7771 begin
7772 x := 0;
7773 MemoryStream.Position := 0;
7774
7775 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7776 WriteLn ('Before setlength.');
7777 {$endif}
7778
7779 SetLength (StreamIn, Length (StreamIn) + 1);
7780 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create;
7781 x := Length (StreamIn) - 1;
7782 err := -1;
7783 StreamIn[x].Data.Enabled := false;
7784 StreamIn[x].Data.LibOpen := -1;
7785 StreamIn[x].Data.lastbuf := -1;
7786 StreamIn[x].Data.levelEnable := 0;
7787 StreamIn[x].Data.positionEnable := 0;
7788 StreamIn[x].Data.levelArrayEnable := 0;
7789 StreamIn[x].data.MemoryStream := MemoryStream;
7790 StreamIn[x].data.MemoryStream.Position := 0;
7791
7792 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7793 WriteLn ('Length (StreamIn) = '+ inttostr (x));
7794 {$endif}
7795
7796 {$IF DEFINED (sndfile)}
7797 if ( (TypeAudio = -1) or (TypeAudio = 0)) and (uosLoadResult.SFloadERROR = 0) then
7798 begin
7799 with sfVirtual do
7800 begin
7801 sf_vio_get_filelen := @m_get_filelen;
7802 seek := @m_seek;
7803 read := @m_read;
7804 write := @m_write;
7805 tell := @m_tell;
7806 end;
7807 try
7808 Streamin [x] .Data.HandleSt := sf_open_virtual (@sfVirtual, SFM_READ, @sfInfo, @StreamIn[x].Data.MemoryStream);
7809 except
7810 StreamIn[x].Data.HandleSt := Nil;
7811 end;
7812 (* try to open the file *)
7813 if StreamIn[x].Data.HandleSt = nil then
7814 begin
7815 StreamIn[x].Data.LibOpen := -1;
7816 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7817 WriteLn ('sf_open_virtual NOT OK');
7818 {$endif}
7819 end
7820 else
7821 begin
7822 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7823 WriteLn ('sf_open_virtual OK');
7824 {$endif}
7825
7826 if SampleFormat = -1 then
7827 StreamIn[x].Data.SampleFormat := 2
7828 else StreamIn[x].Data.SampleFormat := SampleFormat;
7829 StreamIn[x].Data.LibOpen := 0;
7830 StreamIn[x].Data.channels := SFinfo.channels;
7831 if FramesCount = -1 then
7832 StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
7833 else StreamIn[x].Data.Wantframes := FramesCount;
7834
7835 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.Channels);
7836
7837 StreamIn[x].Data.hdformat := SFinfo.format;
7838 StreamIn[x].Data.frames := SFinfo.frames;
7839 StreamIn[x].Data.samplerate := SFinfo.samplerate;
7840 StreamIn[x].Data.samplerateroot := SFinfo.samplerate;
7841 StreamIn[x].Data.sections := SFinfo.sections;
7842 StreamIn[x].Data.copyright := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_COPYRIGHT);
7843 StreamIn[x].Data.software := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_SOFTWARE);
7844 StreamIn[x].Data.comment := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_COMMENT);
7845 StreamIn[x].Data.artist := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_ARTIST);
7846 StreamIn[x].Data.title := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_TITLE);
7847 StreamIn[x].Data.date := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_DATE);
7848 StreamIn[x].Data.track := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_TRACKNUMBER);
7849 StreamIn[x].Data.genre := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_GENRE);
7850 StreamIn[x].Data.album := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_ALBUM);
7851 StreamIn[x].Data.Length := sfInfo.frames;
7852 err := 0;
7853 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7854 WriteLn ('sf_open END OK');
7855 {$endif}
7856 end;
7857 end;
7858 {$endif}
7859
7860 {$IF DEFINED (xmp)}
7861 if ( (StreamIn[x].Data.LibOpen = -1)) then
7862 if ( (TypeAudio = 5)) and (uosLoadResult.XMloadERROR = 0) then
7863 begin
7864 StreamIn[x].Data.HandleSt := xmp_create_context ();
7865 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7866 if StreamIn[x].Data.HandleSt = nil then WriteLn (' xmp_create_context () NOT OK')
7867 else WriteLn ('xmp_create_context () OK');
7868 {$endif}
7869
7870 if xmp_load_module_from_memory (StreamIn[x].Data.HandleSt,
7871 StreamIn[x].Data.MemoryStream.Memory,
7872 StreamIn[x].Data.MemoryStream.size) <> 0 then
7873 begin
7874 StreamIn[x].Data.LibOpen := -1;
7875 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7876 WriteLn ('xmp_load_module_from_memory NOT OK');
7877 {$endif}
7878 end
7879 else
7880 begin
7881 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7882 WriteLn ('xmp_load_module_from_memory OK');
7883 {$endif}
7884
7885 xmp_start_player (StreamIn[x].Data.HandleSt, 44100, 0);
7886 xmp_get_module_info (StreamIn[x].Data.HandleSt, mi);
7887 // xmp_get_frame_info (StreamIn[x].Data.HandleSt , fi);
7888
7889 StreamIn[x].Data.LibOpen := 5;
7890 StreamIn[x].Data.channels := 2;
7891 // todo
7892
7893 if SampleFormat = -1 then
7894 StreamIn[x].Data.SampleFormat := 2
7895 else
7896 StreamIn[x].Data.SampleFormat := SampleFormat;
7897 // Need conversion because xmp is always 16 bit
7898
7899 if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
7900 else
7901 StreamIn[x].Data.Wantframes := FramesCount;
7902
7903 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.Channels);
7904
7905 x2 := 0;
7906 while x2 < Length (Streamin[x].Data.Buffer) do
7907 begin
7908 Streamin[x].Data.Buffer[x2] := 0.0;
7909 inc (x2);
7910 end;
7911
7912 StreamIn[x].Data.samplerate := 44100;
7913 StreamIn[x].Data.samplerateroot := 44100;
7914 StreamIn[x].Data.title := String (mi.module^.Name);
7915 StreamIn[x].Data.copyright := '';
7916 StreamIn[x].Data.software := '';
7917 StreamIn[x].Data.comment := String (mi.module^.typ);
7918 StreamIn[x].Data.artist := String (mi.comment);
7919 StreamIn[x].Data.date := '';
7920 StreamIn[x].Data.track := '';
7921 StreamIn[x].Data.genre := '';
7922 StreamIn[x].Data.album := '';
7923 StreamIn[x].Data.Length := 0;
7924
7925 err := 0;
7926 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7927 WriteLn ('XMP_open END OK');
7928 {$endif}
7929
7930 end;
7931 end;
7932 {$endif}
7933
7934 {$IF DEFINED (mpg123)}
7935 // mpg123
7936 if ( ((TypeAudio = 1) and (StreamIn[x].Data.LibOpen = -1)
7937 and (uosLoadResult.MPloadERROR = 0))) then
7938 begin
7939 Err := -1;
7940 StreamIn[x].Data.HandleSt := mpg123_new (Nil, Err);
7941
7942 if Err = 0 then
7943 begin
7944 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7945 WriteLn ('mpg123_new OK');
7946 {$endif}
7947
7948 if SampleFormat = -1 then
7949 StreamIn[x].Data.SampleFormat := 2
7950 else StreamIn[x].Data.SampleFormat := SampleFormat;
7951
7952 mpg123_format_none (StreamIn[x].Data.HandleSt);
7953
7954 case StreamIn[x].Data.SampleFormat of
7955 0: mpg123_format (StreamIn[x].Data.HandleSt,
7956 DefRate, Stereo,
7957 MPG123_ENC_FLOAT_32);
7958 1: mpg123_format (StreamIn[x].Data.HandleSt,
7959 DefRate, Stereo,
7960 MPG123_ENC_SIGNED_32);
7961 2: mpg123_format (StreamIn[x].Data.HandleSt,
7962 DefRate, Stereo,
7963 MPG123_ENC_SIGNED_16);
7964 end;
7965
7966 err := mpg123_replace_reader_handle (StreamIn[x].
7967 Data.HandleSt, @mpg_read_stream, @
7968 mpg_seek_stream, Nil);
7969
7970 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7971 if err = 0 then
7972 writeln (
7973 '===> mpg123_replace_reader_handle => ok.')
7974 else writeln (
7975 '===> mpg123_replace_reader_handle => NOT OK.');
7976 {$endif}
7977
7978 Err := mpg123_open_handle (StreamIn[x].Data.HandleSt,
7979 pointer (StreamIn[x].Data.MemoryStream));
7980
7981 {$IF DEFINED (uos_debug) and DEFINED (unix)}
7982 if err = 0 then
7983 writeln ('===> mpg123_open_handle => ok.')
7984 else
7985 writeln ('===> mpg123_open_handle => NOT ok.');
7986 {$endif}
7987
7988 sleep (10);
7989 end
7990 else
7991 begin
7992 StreamIn[x].Data.LibOpen := -1;
7993 end;
7994
7995 samprat := roundmath (StreamIn[x].Data.samplerate);
7996
7997 if Err = 0 then Err := mpg123_getformat (StreamIn[x].
7998 Data.HandleSt,
7999 samprat,
8000 StreamIn[x].Data.channels,
8001 StreamIn[x].Data.encoding);
8002
8003 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8004 if err = 0 then
8005 writeln ('===> mpg123_getformat => ok.')
8006 else writeln ('===> mpg123_getformat => NOT ok.');
8007 {$endif}
8008
8009 if Err = 0 then
8010 begin
8011 mpg123_close (StreamIn[x].Data.HandleSt);
8012 mpg123_delete (StreamIn[x].Data.HandleSt);
8013
8014 // Close handle and reload with forced resolution
8015 StreamIn[x].Data.HandleSt := mpg123_new (Nil, Err);
8016
8017 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8018 if err = 0 then
8019 writeln ('===> mpg123_open_handle => ok.')
8020 else writeln (
8021 '===> mpg123_open_handle => NOT ok.');
8022 {$endif}
8023 StreamIn[x].Data.HandleSt := Nil;
8024 StreamIn[x].Data.HandleSt := mpg123_new (Nil, Err);
8025
8026 mpg123_format_none (StreamIn[x].Data.HandleSt);
8027
8028 samprat := roundmath (StreamIn[x].Data.samplerate);
8029
8030
8031 case StreamIn[x].Data.SampleFormat of
8032 0: mpg123_format (StreamIn[x].Data.HandleSt,
8033 samprat,
8034 StreamIn[x].Data.channels,
8035 StreamIn[x].Data.encoding);
8036 1: mpg123_format (StreamIn[x].Data.HandleSt,
8037 samprat,
8038 StreamIn[x].Data.channels,
8039 StreamIn[x].Data.encoding);
8040 2: mpg123_format (StreamIn[x].Data.HandleSt,
8041 samprat,
8042 StreamIn[x].Data.channels,
8043 StreamIn[x].Data.encoding);
8044 end;
8045
8046 err := mpg123_replace_reader_handle (StreamIn[x].
8047 Data.HandleSt, @mpg_read_stream, @mpg_seek_stream, Nil);
8048
8049 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8050 if err = 0 then
8051 writeln ('===> mpg123_replace_reader_handle => ok.')
8052 else writeln ('===> mpg123_replace_reader_handle => NOT OK.');
8053 {$endif}
8054
8055 Err := mpg123_open_handle (StreamIn[x].Data.
8056 HandleSt, pointer (StreamIn[x].Data.
8057 MemoryStream));
8058
8059 samprat := roundmath (StreamIn[x].Data.samplerate);
8060
8061 mpg123_getformat (StreamIn[x].Data.HandleSt,
8062 samprat,
8063 StreamIn[x].Data.channels,
8064 StreamIn[x].Data.encoding);
8065
8066 if FramesCount = -1 then
8067 StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
8068 else StreamIn[x].Data.Wantframes := FramesCount;
8069
8070 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].
8071 Data.Wantframes*StreamIn[x].Data.
8072 Channels);
8073 mpg123_info (StreamIn[x].Data.HandleSt, MPinfo);
8074
8075 // problems with mpg123 library
8076 mpg123_id3 (StreamIn[x].Data.HandleSt, @mpid3v1, @mpid3v2);
8077 // to do : add id2v2
8078 if (mpid3v1 <> nil) and (mpid3v1^ <> nil) then
8079 begin
8080 refmpid3v1 := mpid3v1^^;
8081 StreamIn[x].Data.title := trim (refmpid3v1.title);
8082 StreamIn[x].Data.artist := refmpid3v1.artist;
8083 StreamIn[x].Data.album := refmpid3v1.album;
8084 StreamIn[x].Data.date := refmpid3v1.year;
8085 StreamIn[x].Data.comment := refmpid3v1.comment;
8086 //StreamIn[x].Data.track := refmpid3v1.comment;
8087 StreamIn[x].Data.tag := refmpid3v1.tag;
8088 StreamIn[x].Data.genre := inttostr (refmpid3v1.genre);
8089 end;
8090
8091 StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate;
8092 StreamIn[x].Data.hdformat := MPinfo.layer;
8093 StreamIn[x].Data.frames := MPinfo.framesize;
8094
8095 if StreamIn[x].Data.SampleFormat = 0 then
8096 mpg123_param (StreamIn[x].Data.HandleSt,
8097 StreamIn[x].Data.Channels,
8098 MPG123_FORCE_FLOAT, 0);
8099
8100 StreamIn[x].Data.LibOpen := 1;
8101 StreamIn[x].Data.Length := mpg123_length (StreamIn[x].Data.HandleSt);
8102
8103 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8104 {
8105 writeln ('StreamIn[x].Data.Length = ' + inttostr (
8106 mpg123_length (StreamIn[x].Data.HandleSt);
8107 writeln ('StreamIn[x].Data.frames = ' + inttostr (
8108 StreamIn[x].Data.frames));
8109 writeln ('END StreamIn[x].Data.samplerate = ' +
8110 inttostr (roundmath (StreamIn[x].Data.samplerate)));
8111 writeln ('END StreamIn[x].Data.channels = ' +
8112 inttostr (StreamIn[x].Data.channels));
8113 }
8114 {$endif}
8115 end
8116 else
8117 begin
8118 StreamIn[x].Data.LibOpen := -1;
8119 end;
8120 end;
8121 {$endif}
8122
8123 {$IF DEFINED (opus)}
8124 if ( (TypeAudio = 2) and (StreamIn[x].Data.LibOpen = -1) and
8125 (uosLoadResult.OPloadERROR = 0))
8126
8127 then
8128 begin
8129 Err := -1;
8130
8131 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8132 WriteLn ('Before Opus');
8133 {$endif}
8134
8135 StreamIn[x].Data.HandleSt := pchar ('opus');
8136
8137 if FramesCount= -1 then
8138 totsamples := 4096
8139 else totsamples := FramesCount;
8140
8141 PipeBufferSize := StreamIn[x].Data.MemoryStream.size;
8142
8143 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8144 WriteLn ('totsamples: ' + inttostr (totsamples));
8145 WriteLn ('PipeBufferSize: ' + inttostr (PipeBufferSize));
8146 {$endif}
8147
8148 len := 1;
8149 len2 := 0;
8150
8151 setlength (buffadd, PipeBufferSize);
8152 setlength (StreamIn[x].data.BufferTMP, PipeBufferSize);
8153
8154 while (len2 < PipeBufferSize) and (len > 0) do
8155 begin
8156 len := StreamIn[x].Data.MemoryStream.Read (buffadd[0],PipeBufferSize-len2);
8157
8158 if len > 0 then
8159 for i := 0 to len -1 do
8160 StreamIn[x].data.BufferTMP[i+len2] := buffadd[i];
8161 len2 := len2 + len;
8162 end;
8163
8164 // memory stream not needed anymore ---> converted into buffer
8165 freeandnil (StreamIn[x].Data.MemoryStream);
8166
8167 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8168 WriteLn ('PipeBufferSize = ' + inttostr (PipeBufferSize));
8169 WriteLn ('Data.MemoryStream.Read = ' + inttostr (len2));
8170 WriteLn ('----------------------------------');
8171 //writeln (tencoding.utf8.getstring (StreamIn[x].data.BufferTMP));
8172 {$endif}
8173
8174 StreamIn[x].Data.HandleSt := pchar ('opusstream');
8175
8176 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8177 WriteLn ('StreamIn[x].Data.HandleSt assisgned');
8178 {$endif}
8179
8180 // this is a memorystream converted into a buffer, it works...
8181 StreamIn[x].Data.HandleOP := op_test_memory (StreamIn[x].data.BufferTMP[0],PipeBufferSize, Err);
8182
8183 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8184 WriteLn ('op_test_file error = '+ inttostr (Err));
8185 {$endif}
8186
8187 if Err=0 then
8188 begin
8189 Err := op_test_open (StreamIn[x].Data.HandleOP);
8190 if (Err=0) and (op_link_count (StreamIn[x].Data.HandleOP)=1) then
8191 begin
8192 if SampleFormat = -1 then
8193 StreamIn[x].Data.SampleFormat := 2
8194 else StreamIn[x].Data.SampleFormat := SampleFormat;
8195
8196 //tag
8197 OpusTag := op_tags (StreamIn[x].Data.HandleOP, Nil);
8198
8199 if OpusTag<>nil then
8200 begin
8201 if OpusTag^.comments>0 then
8202 begin
8203 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8204 WriteLn ((Format ('OpusTag.comments = %d', [OpusTag^.comments])));
8205 {$endif}
8206 LComment := OpusTag^.user_comments;
8207 LcommentLength := OpusTag^.comment_lengths;
8208 for j := 0 to OpusTag^.comments - 1 do
8209 begin
8210 SetLength (s, LcommentLength^);
8211 move (Pointer (LComment^)^, Pointer (s)^, LcommentLength^);
8212
8213 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8214 // WriteLn (s);
8215 {$endif}
8216
8217 if j = 1 then StreamIn[x].Data.title := s;
8218 if j = 2 then StreamIn[x].Data.artist := s;
8219 if j = 3 then StreamIn[x].Data.album := s;
8220 if j = 4 then StreamIn[x].Data.date := s;
8221 if j = 5 then StreamIn[x].Data.comment := s;
8222 if j = 6 then StreamIn[x].Data.tag := s;
8223
8224 inc (LComment);
8225 inc (LcommentLength);
8226 end;
8227 end;
8228 end;
8229
8230 // WriteLn ((Format ('op_bitrate = %d', [op_bitrate (StreamIn[x].Data.HandleOP, nil)])));
8231
8232 StreamIn[x].Data.Length := op_pcm_total (StreamIn[x].Data.HandleOP, Nil);
8233 StreamIn[x].Data.channels := op_channel_count (StreamIn[x].Data.HandleOP, Nil);
8234 StreamIn[x].Data.bitrate := op_bitrate (StreamIn[x].Data.HandleOP, Nil);
8235
8236 // opus use constant sample rate 48k
8237 StreamIn[x].Data.samplerate := 48000;
8238 StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate;
8239 StreamIn[x].Data.Seekable := true;
8240
8241 if FramesCount = -1 then
8242 StreamIn[x].Data.Wantframes := 4096 * StreamIn[x].Data.Channels
8243 else StreamIn[x].Data.Wantframes := FramesCount;
8244
8245 SetLength (StreamIn[x].Data.Buffer,
8246 StreamIn[x].Data.Wantframes*StreamIn[x].Data.Channels);
8247
8248 StreamIn[x].Data.LibOpen := 4;
8249 end
8250 else
8251 begin
8252 StreamIn[x].Data.LibOpen := -1;
8253 end;
8254 end;
8255 end;
8256 {$endif}
8257
8258 {$IF DEFINED (neaac)}
8259 if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.AAloadERROR = 0) then
8260 begin
8261 Err := -1;
8262
8263 StreamIn[x].AACI := TAACInfo.Create ();
8264
8265 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8266 WriteLn ('TAACInfo.Create () = ok');
8267 {$endif}
8268 {
8269 Case SampleFormat of
8270 0 : StreamIn[x].AACI:= MP4OpenFile (FileName, FAAD_FMT_FLOAT);
8271 1 : StreamIn[x].AACI:= MP4OpenFile (FileName, FAAD_FMT_32BIT);
8272 2 : StreamIn[x].AACI:= MP4OpenFile (FileName, FAAD_FMT_16BIT);
8273 End;
8274 }
8275 if StreamIn[x].AACI <> nil then
8276 begin
8277 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8278 WriteLn ('MP4OpenFile () = ok');
8279 {$endif}
8280
8281 case StreamIn[x].AACI.outputFormat of
8282 FAAD_FMT_16BIT : StreamIn[x].Data.SampleFormat := 2;
8283 //FAAD_FMT_24BIT :;
8284 FAAD_FMT_32BIT : StreamIn[x].Data.SampleFormat := 1;
8285 FAAD_FMT_FLOAT : StreamIn[x].Data.SampleFormat := 0;
8286 //FAAD_FMT_DOUBLE:;
8287 end;
8288
8289 StreamIn[x].Data.HandleSt := StreamIn[x].AACI.hMP4;
8290 StreamIn[x].Data.samplerate := StreamIn[x].AACI.SampleRate;
8291 StreamIn[x].Data.channels := StreamIn[x].AACI.Channels;
8292
8293 case StreamIn[x].AACI.outputFormat of
8294 FAAD_FMT_16BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
8295 //FAAD_FMT_24BIT :;
8296 FAAD_FMT_32BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_32;
8297 FAAD_FMT_FLOAT : StreamIn[x].Data.encoding := MPG123_ENC_FLOAT_32;
8298 //FAAD_FMT_DOUBLE:;
8299 end;
8300
8301 if FramesCount = -1 then
8302 StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
8303 else StreamIn[x].Data.Wantframes := FramesCount;
8304
8305 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels);
8306
8307 StreamIn[x].Data.title := StreamIn[x].AACI.Title;
8308 StreamIn[x].Data.artist := StreamIn[x].AACI.Artist;
8309 StreamIn[x].Data.album := StreamIn[x].AACI.Album;
8310 StreamIn[x].Data.date := StreamIn[x].AACI.Date;
8311 StreamIn[x].Data.comment := StreamIn[x].AACI.Comment;
8312 StreamIn[x].Data.tag[0] := #0;
8313 StreamIn[x].Data.tag[1] := #0;
8314 StreamIn[x].Data.tag[2] := #0;
8315 StreamIn[x].Data.genre := StreamIn[x].AACI.Genre;
8316 StreamIn[x].Data.samplerateroot := StreamIn[x].AACI.SampleRate;
8317 StreamIn[x].Data.hdformat := 0;
8318 StreamIn[x].Data.frames := 0;
8319 StreamIn[x].Data.Length := StreamIn[x].AACI.TotalSamples;
8320 StreamIn[x].Data.Seekable := StreamIn[x].AACI.Size > 0;
8321 StreamIn[x].Data.LibOpen := 2;
8322 Err := 0;
8323 end
8324 else
8325 begin
8326 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8327 WriteLn ('MP4OpenFile () NOT ok');
8328 {$endif}
8329 end;
8330 end;
8331 {$endif}
8332
8333 {$IF DEFINED (cdrom)}
8334 if (StreamIn[x].Data.LibOpen = -1) then
8335 begin
8336 Err := -1;
8337 StreamIn[x].pCD := Nil;
8338
8339 case SampleFormat of
8340 2 : StreamIn[x].pCD := CDROM_OpenFile (StreamIn[x].Data.FileName);
8341 end;
8342
8343 if StreamIn[x].pCD <> nil then
8344 begin
8345 case StreamIn[x].pCD^.BitsPerSample of
8346 16 : StreamIn[x].Data.SampleFormat := 2;
8347 end;
8348 StreamIn[x].Data.HandleSt := @StreamIn[x].pCD;
8349 // Uos requires an assigned pointer....
8350 StreamIn[x].Data.samplerate := StreamIn[x].pCD^.SampleRate;
8351 StreamIn[x].Data.channels := StreamIn[x].pCD^.Channels;
8352
8353 case StreamIn[x].pCD^.BitsPerSample of
8354 16 : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
8355 end;
8356
8357 if FramesCount = -1 then
8358 StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
8359 else StreamIn[x].Data.Wantframes := FramesCount;
8360
8361 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels);
8362
8363 StreamIn[x].Data.title := '';
8364 StreamIn[x].Data.artist := '';
8365 StreamIn[x].Data.album := '';
8366 StreamIn[x].Data.date := '';
8367 StreamIn[x].Data.comment := '';
8368 StreamIn[x].Data.tag[0] := #0;
8369 StreamIn[x].Data.tag[1] := #0;
8370 StreamIn[x].Data.tag[2] := #0;
8371 StreamIn[x].Data.genre := 0;
8372 StreamIn[x].Data.samplerateroot := StreamIn[x].pCD^.SampleRate;
8373 StreamIn[x].Data.hdformat := 0;
8374 StreamIn[x].Data.frames := 0;
8375 StreamIn[x].Data.Length := StreamIn[x].pCD^.TotalSamples;
8376 StreamIn[x].Data.LibOpen := 3;
8377 Err := 0;
8378 end;
8379 end;
8380 {$endif}
8381
8382 if err <> 0 then
8383 begin
8384 result := -1;
8385 StreamIn[Length (StreamIn) - 1].Destroy;
8386 setlength (StreamIn, Length (StreamIn) - 1);
8387 end
8388 else
8389 begin
8390 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8391 WriteLn ('addfrom memorystream OK');
8392 {$endif}
8393 Result := x;
8394 StreamIn[x].Data.Output := OutputIndex;
8395 StreamIn[x].Data.Status := 1;
8396 StreamIn[x].Data.Position := 0;
8397 StreamIn[x].Data.OutFrames := 0;
8398 StreamIn[x].Data.Poseek := -1;
8399 StreamIn[x].Data.TypePut := 0;
8400 StreamIn[x].Data.seekable := True;
8401 StreamIn[x].LoopProc := Nil;
8402 if SampleFormat = -1 then
8403 StreamIn[x].Data.SampleFormat := 2
8404 else StreamIn[x].Data.SampleFormat := SampleFormat;
8405
8406 case StreamIn[x].Data.LibOpen of
8407 -1:;
8408 {$IF DEFINED (sndfile)}
8409 0: StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
8410 {$endif}
8411 {$IF DEFINED (mpg123)}
8412 1:
8413 begin
8414 if StreamIn[x].Data.SampleFormat = 2 then
8415 StreamIn[x].Data.ratio := streamIn[x].Data.Channels
8416 else StreamIn[x].Data.ratio := 2 * streamIn[x].Data.Channels;
8417
8418 if StreamIn[x].Data.SampleFormat = 0 then
8419 mpg123_param (StreamIn[x].Data.HandleSt, StreamIn[x].Data.Channels,
8420 MPG123_FORCE_FLOAT, 0);
8421 end;
8422 {$endif}
8423 {$IF DEFINED (neaac)}
8424 2 : StreamIn[x].Data.ratio := streamIn[x].AACI.Channels;
8425 {$endif}
8426 {$IF DEFINED (cdrom)}
8427 3 : StreamIn[x].Data.ratio := streamIn[x].pCD^.Channels;
8428 {$endif}
8429 {$IF DEFINED (opus)}
8430 4 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
8431 {$endif}
8432 {$IF DEFINED (xmp)}
8433 5 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
8434 {$endif}
8435 end;
8436
8437 StreamIn[x].Data.Enabled := True;
8438 end;
8439 end;
8440end;
8441
8442
8443// Add an Input from Audio file with Custom parameters
8444// FileName : filename of audio file
8445// OutputIndex : OutputIndex of existing Output// -1: all output, -2: no output, other cint32 : existing Output
8446// SampleFormat : -1 default: Int16 (0: Float32, 1:Int32, 2:Int16)
8447// FramesCount : default: -1 (65536 div channels)
8448// example : InputIndex := AddFromFile ('/usr/home/test.ogg',-1,-1,-1);
8449function Tuos_Player.AddFromFile(Filename: Pchar; OutputIndex: cint32;
8450 SampleFormat: cint32; FramesCount: cint32): cint32;
8451var
8452 x, x2, err: cint32;
8453
8454 samprat : integer;
8455
8456 {$IF DEFINED (sndfile)}
8457 sfInfo: TSF_INFO;
8458 {$endif}
8459
8460 {$IF DEFINED (opus)}
8461 s: UTF8String;
8462 j: Integer;
8463 OpusTag: POpusTags;
8464 LComment: PPAnsiChar;
8465 LcommentLength: PInteger;
8466 {$endif}
8467
8468 {$IF DEFINED (xmp)}
8469 mi: xmp_module_info;
8470 fi: xmp_frame_info;
8471 {$endif}
8472
8473 {$IF DEFINED (mpg123)}
8474 mpinfo: Tmpg123_frameinfo;
8475 BufferTag: array[1..128] of char;
8476 F: file;
8477 // problems with mpg123
8478 // mpid3v2: Tmpg123_id3v2;
8479 {$endif}
8480
8481begin
8482 result := -1;
8483
8484 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8485 WriteLn ('Before all.');
8486 {$endif}
8487
8488 if fileexists (filename) then
8489 begin
8490 x := 0;
8491
8492 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8493 WriteLn ('Before setlength.');
8494 {$endif}
8495
8496 SetLength (StreamIn, Length (StreamIn) + 1);
8497 StreamIn[Length (StreamIn) - 1] := Tuos_InStream.Create;
8498 x := Length (StreamIn) - 1;
8499 err := -1;
8500 StreamIn[x].Data.Enabled := false;
8501 StreamIn[x].Data.LibOpen := -1;
8502 StreamIn[x].Data.levelEnable := 0;
8503 StreamIn[x].Data.positionEnable := 0;
8504 StreamIn[x].Data.levelArrayEnable := 0;
8505 StreamIn[x].Data.lastbuf := 0;
8506
8507 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8508 WriteLn ('Length (StreamIn) = '+ inttostr (x));
8509 {$endif}
8510
8511 {$IF DEFINED (sndfile)}
8512 if (uosLoadResult.SFloadERROR = 0) then
8513 begin
8514
8515 StreamIn[x].Data.HandleSt := sf_open (FileName, SFM_READ, sfInfo);
8516
8517 (* try to open the file *)
8518 if StreamIn[x].Data.HandleSt = nil then
8519 begin
8520 StreamIn[x].Data.LibOpen := -1;
8521 err := -1;
8522 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8523 WriteLn ('sf_open NOT OK');
8524 {$endif}
8525 end
8526 else
8527 begin
8528 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8529 WriteLn ('sf_open OK');
8530 {$endif}
8531 StreamIn[x].Data.LibOpen := 0;
8532 StreamIn[x].Data.filename := FileName;
8533 StreamIn[x].Data.channels := SFinfo.channels;
8534
8535 if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.
8536 Channels
8537 else
8538 StreamIn[x].Data.Wantframes := FramesCount;
8539
8540 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
8541 Channels);
8542 x2 := 0;
8543 while x2 < Length (Streamin[x].Data.Buffer) do
8544 begin
8545 Streamin[x].Data.Buffer[x2] := 0.0;
8546 inc (x2);
8547 end;
8548
8549 if SampleFormat = -1 then
8550 StreamIn[x].Data.SampleFormat := 2
8551 else
8552 StreamIn[x].Data.SampleFormat := SampleFormat;
8553
8554 StreamIn[x].Data.hdformat := SFinfo.format;
8555 StreamIn[x].Data.frames := SFinfo.frames;
8556 StreamIn[x].Data.samplerate := SFinfo.samplerate;
8557 StreamIn[x].Data.samplerateroot := SFinfo.samplerate;
8558 StreamIn[x].Data.sections := SFinfo.sections;
8559 StreamIn[x].Data.title := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_TITLE);
8560 StreamIn[x].Data.copyright := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_COPYRIGHT);
8561 StreamIn[x].Data.software := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_SOFTWARE);
8562 StreamIn[x].Data.comment := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_COMMENT);
8563 StreamIn[x].Data.artist := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_ARTIST);
8564 StreamIn[x].Data.date := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_DATE);
8565 StreamIn[x].Data.track := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_TRACKNUMBER);
8566 StreamIn[x].Data.genre := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_GENRE);
8567 StreamIn[x].Data.album := sf_get_string (StreamIn[x].Data.HandleSt, SF_STR_ALBUM);
8568
8569 StreamIn[x].Data.Length := sfInfo.frames;
8570 err := 0;
8571 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8572 WriteLn ('sf_open END OK');
8573 {$endif}
8574 end;
8575 end;
8576
8577 {$endif}
8578
8579 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8580 WriteLn ('sf StreamIn[x].Data.LibOpen = ' + inttostr (StreamIn[x].Data.LibOpen));
8581 WriteLn ('sf err = ' + inttostr (err));
8582 {$endif}
8583
8584 // XMP
8585 {$IF DEFINED (xmp)}
8586 if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.XMloadERROR = 0) then
8587 begin
8588 Err := -1;
8589
8590 StreamIn[x].Data.HandleSt := xmp_create_context ();
8591 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8592 if StreamIn[x].Data.HandleSt = nil then WriteLn (' xmp_create_context () NOT OK')
8593 else WriteLn (' xmp_create_context () OK');
8594 {$endif}
8595
8596 if xmp_load_module (StreamIn[x].Data.HandleSt, PChar (FileName)) <> 0 then
8597 begin
8598 StreamIn[x].Data.LibOpen := -1;
8599 err := -1;
8600 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8601 WriteLn ('xmp_load_module NOT OK');
8602 {$endif}
8603 end
8604 else
8605 begin
8606
8607 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8608 WriteLn ('xmp_load_module () = ok');
8609 {$endif}
8610 xmp_start_player (StreamIn[x].Data.HandleSt, 44100, 0);
8611 xmp_get_module_info (StreamIn[x].Data.HandleSt, mi);
8612 xmp_get_frame_info (StreamIn[x].Data.HandleSt , fi);
8613
8614 StreamIn[x].Data.LibOpen := 5;
8615 StreamIn[x].Data.filename := FileName;
8616 StreamIn[x].Data.channels := 2;
8617
8618 if SampleFormat = -1 then
8619 StreamIn[x].Data.SampleFormat := 2
8620 else
8621 StreamIn[x].Data.SampleFormat := SampleFormat;
8622 // Need conversion because xmp is always 16 bit
8623
8624 if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.
8625 Channels
8626 else
8627 StreamIn[x].Data.Wantframes := FramesCount;
8628
8629 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
8630 Channels);
8631 x2 := 0;
8632 while x2 < Length (Streamin[x].Data.Buffer) do
8633 begin
8634 Streamin[x].Data.Buffer[x2] := 0.0;
8635 inc (x2);
8636 end;
8637
8638 StreamIn[x].Data.hdformat := 0;
8639 StreamIn[x].Data.frames := 0;
8640 StreamIn[x].Data.samplerate := 44100;
8641 StreamIn[x].Data.samplerateroot := 44100;
8642 // StreamIn[x].Data.sections := SFinfo.sections;
8643 StreamIn[x].Data.title := String (mi.module^.Name);
8644 StreamIn[x].Data.copyright := '';
8645 StreamIn[x].Data.software := '';
8646 StreamIn[x].Data.comment := String (mi.module^.typ);
8647 StreamIn[x].Data.artist := String (mi.comment);
8648 StreamIn[x].Data.date := '';
8649 StreamIn[x].Data.track := '';
8650 StreamIn[x].Data.genre := '';
8651 StreamIn[x].Data.album := '';
8652 StreamIn[x].Data.Length := round(fi.total_time * StreamIn[x].Data.samplerate / 1000);
8653
8654 err := 0;
8655 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8656 WriteLn ('XMP_open END OK');
8657 {$endif}
8658 end;
8659 end;
8660 {$endif}
8661
8662 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8663 WriteLn ('XMP StreamIn[x].Data.LibOpen = ' + inttostr (StreamIn[x].Data.LibOpen));
8664 WriteLn ('XMP err = ' + inttostr (err));
8665 {$endif}
8666
8667 {$IF DEFINED (mpg123)}
8668 if ( (StreamIn[x].Data.LibOpen = -1)) and (uosLoadResult.MPloadERROR = 0) then
8669 begin
8670 Err := -1;
8671
8672 StreamIn[x].Data.HandleSt := mpg123_new (Nil, Err);
8673
8674 if Err = 0 then
8675 begin
8676
8677 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8678 WriteLn ('mpg123_new OK');
8679 {$endif}
8680
8681 if SampleFormat = -1 then
8682 StreamIn[x].Data.SampleFormat := 2
8683 else
8684 StreamIn[x].Data.SampleFormat := SampleFormat;
8685 mpg123_format_none (StreamIn[x].Data.HandleSt);
8686 case StreamIn[x].Data.SampleFormat of
8687 0: mpg123_format (StreamIn[x].Data.HandleSt, DefRate, Stereo,
8688 MPG123_ENC_FLOAT_32);
8689 1: mpg123_format (StreamIn[x].Data.HandleSt, DefRate, Stereo,
8690 MPG123_ENC_SIGNED_32);
8691 2: mpg123_format (StreamIn[x].Data.HandleSt, DefRate, Stereo,
8692 MPG123_ENC_SIGNED_16);
8693 end;
8694
8695 Err := mpg123_open (StreamIn[x].Data.HandleSt, PChar (FileName));
8696 end
8697 else
8698 begin
8699 StreamIn[x].Data.LibOpen := -1;
8700 end;
8701
8702 samprat := roundmath (StreamIn[x].Data.samplerate);
8703
8704 if Err = 0 then
8705 Err := mpg123_getformat (StreamIn[x].Data.HandleSt,
8706 samprat, StreamIn[x].Data.channels,
8707 StreamIn[x].Data.encoding);
8708
8709 if Err = 0 then
8710 begin
8711 // Close handle and reload with forced resolution
8712 mpg123_close (StreamIn[x].Data.HandleSt);
8713 mpg123_delete (StreamIn[x].Data.HandleSt);
8714 StreamIn[x].Data.HandleSt := mpg123_new (Nil, Err);
8715
8716 mpg123_format_none (StreamIn[x].Data.HandleSt);
8717 case StreamIn[x].Data.SampleFormat of
8718 0: mpg123_format (StreamIn[x].Data.HandleSt, samprat,
8719 StreamIn[x].Data.channels, StreamIn[x].Data.encoding);
8720 1: mpg123_format (StreamIn[x].Data.HandleSt, samprat,
8721 StreamIn[x].Data.channels, StreamIn[x].Data.encoding);
8722 2: mpg123_format (StreamIn[x].Data.HandleSt, samprat,
8723 StreamIn[x].Data.channels, StreamIn[x].Data.encoding);
8724 end;
8725 mpg123_open (StreamIn[x].Data.HandleSt, (PChar (FileName)));
8726 mpg123_getformat (StreamIn[x].Data.HandleSt,
8727 samprat, StreamIn[x].Data.channels,
8728 StreamIn[x].Data.encoding);
8729 StreamIn[x].Data.filename := filename;
8730
8731 if FramesCount = -1 then StreamIn[x].Data.Wantframes :=
8732 65536 Div StreamIn[x].Data.
8733 Channels
8734 else
8735 StreamIn[x].Data.Wantframes := FramesCount;
8736
8737 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
8738 Channels);
8739
8740 mpg123_info (StreamIn[x].Data.HandleSt, MPinfo);
8741
8742 // custom code for reading ID3Tag ---> problems with mpg123_id3 ()
8743
8744 AssignFile (F, Filename);
8745
8746 FileMode := fmOpenRead + fmShareDenyNone;
8747
8748 Reset (F, 1);
8749 Seek (F, FileSize (F) - 128);
8750 BlockRead (F, BufferTag, SizeOf (BufferTag));
8751 CloseFile (F);
8752
8753 StreamIn[x].Data.tag := copy (BufferTag, 1, 3);
8754 StreamIn[x].Data.title := copy (BufferTag, 4, 30);
8755 StreamIn[x].Data.artist := copy (BufferTag, 34, 30);
8756 StreamIn[x].Data.album := copy (BufferTag, 64, 30);
8757 StreamIn[x].Data.date := copy (BufferTag, 94, 4);
8758 StreamIn[x].Data.comment := copy (BufferTag, 98, 30);
8759 StreamIn[x].Data.track := inttostr (ord (BufferTag[127]));
8760 StreamIn[x].Data.genre := inttostr (ord (BufferTag[128]));
8761 StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate;
8762 StreamIn[x].Data.hdformat := MPinfo.layer;
8763 StreamIn[x].Data.frames := MPinfo.framesize;
8764 StreamIn[x].Data.Length := mpg123_length (StreamIn[x].Data.HandleSt);
8765 StreamIn[x].Data.LibOpen := 1;
8766 end
8767 else
8768 begin
8769 StreamIn[x].Data.LibOpen := -1;
8770 end;
8771 end;
8772
8773 {$endif}
8774
8775 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8776 WriteLn ('mp StreamIn[x].Data.LibOpen = ' + inttostr (StreamIn[x].Data.LibOpen));
8777 WriteLn ('mp err = ' + inttostr (err));
8778 {$endif}
8779
8780 {$IF DEFINED (opus)}
8781 if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.OPloadERROR = 0) then
8782 begin
8783 Err := -1;
8784
8785 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8786 WriteLn ('Before Opus');
8787 {$endif}
8788
8789 StreamIn[x].Data.HandleSt := pchar ('opus');
8790 StreamIn[x].Data.HandleOP := op_test_file (PChar (FileName), Err);
8791
8792 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8793 WriteLn ('op_test_file error = '+ inttostr (Err));
8794 {$endif}
8795
8796 if Err=0
8797 then
8798 begin
8799 Err := op_test_open (StreamIn[x].Data.HandleOP);
8800 if (Err=0) and (op_link_count (StreamIn[x].Data.HandleOP)=1)
8801 then
8802 begin
8803
8804 if SampleFormat = -1 then
8805 StreamIn[x].Data.SampleFormat := 2
8806 else
8807 StreamIn[x].Data.SampleFormat := SampleFormat;
8808
8809 OpusTag := op_tags (StreamIn[x].Data.HandleOP, Nil);
8810
8811 if OpusTag<>nil
8812
8813 then
8814 begin
8815 if OpusTag^.comments>0
8816 then
8817 begin
8818 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8819 WriteLn ((Format ('OpusTag.comments = %d', [OpusTag^.comments])));
8820 {$endif}
8821 LComment := OpusTag^.user_comments;
8822 LcommentLength := OpusTag^.comment_lengths;
8823 for j := 0 to OpusTag^.comments - 1 do
8824 begin
8825 SetLength (s, LcommentLength^);
8826 move (Pointer (LComment^)^, Pointer (s)^, LcommentLength^);
8827
8828 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8829 // WriteLn (s);
8830 {$endif}
8831 if j = 1 then StreamIn[x].Data.title := s;
8832 if j = 2 then StreamIn[x].Data.artist := s;
8833 if j = 3 then StreamIn[x].Data.album := s;
8834 if j = 4 then StreamIn[x].Data.date := s;
8835 if j = 5 then StreamIn[x].Data.comment := s;
8836 if j = 6 then StreamIn[x].Data.tag := s;
8837
8838 inc (LComment);
8839 inc (LcommentLength);
8840 end;
8841 end;
8842 end;
8843
8844 // WriteLn ((Format ('op_bitrate = %d', [op_bitrate (StreamIn[x].Data.HandleOP, nil)])));
8845 StreamIn[x].Data.Length := op_pcm_total (StreamIn[x].Data.HandleOP, Nil);
8846 StreamIn[x].Data.filename := FileName;
8847 StreamIn[x].Data.channels := op_channel_count (StreamIn[x].Data.HandleOP, Nil);
8848
8849 // opus use constant sample rate 48k
8850 StreamIn[x].Data.samplerate := 48000;
8851 StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate;
8852 StreamIn[x].Data.Seekable := true;
8853
8854 if FramesCount = -1 then StreamIn[x].Data.Wantframes := 4096 * StreamIn[x].Data.
8855 Channels
8856 else
8857 StreamIn[x].Data.Wantframes := FramesCount;
8858
8859 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
8860 Channels);
8861
8862 StreamIn[x].Data.LibOpen := 4;
8863
8864 end
8865 else
8866 begin
8867 StreamIn[x].Data.LibOpen := -1;
8868 end;
8869 end;
8870 end;
8871{$endif}
8872
8873 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8874 WriteLn ('op StreamIn[x].Data.LibOpen = ' + inttostr (StreamIn[x].Data.LibOpen));
8875 WriteLn ('op err = ' + inttostr (err));
8876 {$endif}
8877
8878 {$IF DEFINED (neaac)}
8879 if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.AAloadERROR = 0) then
8880 begin
8881 Err := -1;
8882
8883 StreamIn[x].AACI := TAACInfo.Create ();
8884
8885 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8886 WriteLn ('TAACInfo.Create () = ok');
8887 {$endif}
8888
8889 case SampleFormat of
8890 0 : StreamIn[x].AACI := MP4OpenFile (FileName, FAAD_FMT_FLOAT);
8891 1 : StreamIn[x].AACI := MP4OpenFile (FileName, FAAD_FMT_32BIT);
8892 2 : StreamIn[x].AACI := MP4OpenFile (FileName, FAAD_FMT_16BIT);
8893 end;
8894
8895 if StreamIn[x].AACI <> nil then
8896 begin
8897 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8898 WriteLn ('MP4OpenFile () = ok');
8899 {$endif}
8900
8901 case StreamIn[x].AACI.outputFormat of
8902 FAAD_FMT_16BIT : StreamIn[x].Data.SampleFormat := 2;
8903 //FAAD_FMT_24BIT :;
8904 FAAD_FMT_32BIT : StreamIn[x].Data.SampleFormat := 1;
8905 FAAD_FMT_FLOAT : StreamIn[x].Data.SampleFormat := 0;
8906 //FAAD_FMT_DOUBLE:;
8907 end;
8908
8909 StreamIn[x].Data.filename := FileName;
8910 StreamIn[x].Data.HandleSt := StreamIn[x].AACI.hMP4;
8911 StreamIn[x].Data.samplerate := StreamIn[x].AACI.SampleRate;
8912 StreamIn[x].Data.channels := StreamIn[x].AACI.Channels;
8913
8914 case StreamIn[x].AACI.outputFormat of
8915 FAAD_FMT_16BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
8916 //FAAD_FMT_24BIT :;
8917 FAAD_FMT_32BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_32;
8918 FAAD_FMT_FLOAT : StreamIn[x].Data.encoding := MPG123_ENC_FLOAT_32;
8919 //FAAD_FMT_DOUBLE:;
8920 end;
8921
8922 if FramesCount = -1 then
8923 StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
8924 else
8925 StreamIn[x].Data.Wantframes := FramesCount;
8926
8927 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels);
8928
8929 StreamIn[x].Data.title := StreamIn[x].AACI.Title;
8930 StreamIn[x].Data.artist := StreamIn[x].AACI.Artist;
8931 StreamIn[x].Data.album := StreamIn[x].AACI.Album;
8932 StreamIn[x].Data.date := StreamIn[x].AACI.Date;
8933 StreamIn[x].Data.comment := StreamIn[x].AACI.Comment;
8934 StreamIn[x].Data.tag[0] := #0;
8935 StreamIn[x].Data.tag[1] := #0;
8936 StreamIn[x].Data.tag[2] := #0;
8937 StreamIn[x].Data.genre := StreamIn[x].AACI.Genre;
8938 StreamIn[x].Data.samplerateroot := StreamIn[x].AACI.SampleRate;
8939 StreamIn[x].Data.hdformat := 0;
8940 StreamIn[x].Data.frames := 0;
8941 StreamIn[x].Data.Length := StreamIn[x].AACI.TotalSamples;
8942 StreamIn[x].Data.Seekable := StreamIn[x].AACI.Size > 0;
8943 StreamIn[x].Data.LibOpen := 2;
8944 Err := 0;
8945 end
8946 else
8947 begin
8948 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8949 WriteLn ('MP4OpenFile () NOT ok');
8950 {$endif}
8951 end;
8952
8953 end;
8954 {$endif}
8955
8956 {$IF DEFINED (uos_debug) and DEFINED (unix)}
8957 WriteLn ('ac StreamIn[x].Data.LibOpen = ' + inttostr (StreamIn[x].Data.LibOpen));
8958 WriteLn ('ac err = ' + inttostr (err));
8959 {$endif}
8960
8961
8962 {$IF DEFINED (cdrom)}
8963 if (StreamIn[x].Data.LibOpen = -1) then
8964 begin
8965 Err := -1;
8966 StreamIn[x].pCD := Nil;
8967
8968 case SampleFormat of
8969 2 : StreamIn[x].pCD := CDROM_OpenFile (FileName);
8970 end;
8971
8972 if StreamIn[x].pCD <> nil then
8973 begin
8974 case StreamIn[x].pCD^.BitsPerSample of
8975 16 : StreamIn[x].Data.SampleFormat := 2;
8976 end;
8977
8978 StreamIn[x].Data.filename := FileName;
8979
8980 StreamIn[x].Data.HandleSt := @StreamIn[x].pCD;
8981 // Uos requires an assigned pointer....
8982
8983 StreamIn[x].Data.samplerate := StreamIn[x].pCD^.SampleRate;
8984 StreamIn[x].Data.channels := StreamIn[x].pCD^.Channels;
8985
8986 case StreamIn[x].pCD^.BitsPerSample of
8987 16 : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
8988 end;
8989
8990 if FramesCount = -1 then
8991 StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
8992 else
8993 StreamIn[x].Data.Wantframes := FramesCount;
8994
8995 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels);
8996
8997 StreamIn[x].Data.title := '';
8998 StreamIn[x].Data.artist := '';
8999 StreamIn[x].Data.album := '';
9000 StreamIn[x].Data.date := '';
9001 StreamIn[x].Data.comment := '';
9002 StreamIn[x].Data.tag[0] := #0;
9003 StreamIn[x].Data.tag[1] := #0;
9004 StreamIn[x].Data.tag[2] := #0;
9005 StreamIn[x].Data.genre := '0';
9006 StreamIn[x].Data.samplerateroot := StreamIn[x].pCD^.SampleRate;
9007 StreamIn[x].Data.hdformat := 0;
9008 StreamIn[x].Data.frames := 0;
9009 StreamIn[x].Data.Length := StreamIn[x].pCD^.TotalSamples;
9010
9011 StreamIn[x].Data.LibOpen := 3;
9012 Err := 0;
9013 end;
9014 end;
9015 {$endif}
9016
9017 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9018 WriteLn ('cd StreamIn[x].Data.LibOpen = ' + inttostr (StreamIn[x].Data.LibOpen));
9019 WriteLn ('cd err = ' + inttostr (err));
9020 {$endif}
9021
9022 if (err <> 0) or (StreamIn[x].Data.LibOpen = -1) then
9023 begin
9024 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9025 WriteLn ('not ok StreamIn[x].Data.LibOpen = -1');
9026 WriteLn ('not ok cd err = ' + inttostr (err));
9027 {$endif}
9028
9029 result := -1;
9030 StreamIn[Length (StreamIn) - 1].Destroy;
9031 setlength (StreamIn, Length (StreamIn) - 1);
9032 end
9033 else
9034 begin
9035
9036 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9037 WriteLn ('addfromfile OK');
9038 {$endif}
9039
9040 Result := x;
9041 StreamIn[x].Data.Output := OutputIndex;
9042 StreamIn[x].Data.Status := 1;
9043 StreamIn[x].Data.Position := 0;
9044 StreamIn[x].Data.OutFrames := 0;
9045 StreamIn[x].Data.Poseek := -1;
9046 StreamIn[x].Data.TypePut := 0;
9047 StreamIn[x].Data.seekable := True;
9048 StreamIn[x].LoopProc := Nil;
9049 if SampleFormat = -1 then
9050 StreamIn[x].Data.SampleFormat := 2
9051 else
9052 StreamIn[x].Data.SampleFormat := SampleFormat;
9053
9054 case StreamIn[x].Data.LibOpen of
9055
9056 0: StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
9057
9058 {$IF DEFINED (mpg123)}
9059 1:
9060 begin
9061 if StreamIn[x].Data.SampleFormat = 2 then
9062 StreamIn[x].Data.ratio := streamIn[x].Data.Channels
9063 else
9064 StreamIn[x].Data.ratio := 2 * streamIn[x].Data.Channels;
9065
9066 if StreamIn[x].Data.SampleFormat = 0 then
9067 mpg123_param (StreamIn[x].Data.HandleSt, StreamIn[x].Data.Channels,
9068 MPG123_FORCE_FLOAT, 0);
9069 end;
9070 {$endif}
9071 {$IF DEFINED (neaac)}
9072 2 : StreamIn[x].Data.ratio := streamIn[x].AACI.Channels;
9073 {$endif}
9074 {$IF DEFINED (cdrom)}
9075 3 : StreamIn[x].Data.ratio := streamIn[x].pCD^.Channels;
9076 {$endif}
9077 {$IF DEFINED (opus)}
9078 4 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
9079 {$endif}
9080 {$IF DEFINED (xmp)}
9081 5 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
9082 {$endif}
9083 end;
9084 StreamIn[x].Data.Enabled := True;
9085 end;
9086 end
9087 else result := -2;
9088
9089 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9090 WriteLn ('result = ' + inttostr (result));
9091 WriteLn ('cd err = ' + inttostr (err));
9092 {$endif}
9093end;
9094
9095procedure Tuos_Player.ReadEndless (x : integer);
9096begin
9097{
9098 Nothing to do: all is done with AddFromEndlessMuted.
9099 }
9100end;
9101
9102{$IF DEFINED (synthesizer)}
9103procedure Tuos_Player.FillLookupTable (x, typewave, channel, AHarmonics: Integer;
9104 EvenHarmonics : shortint);
9105var
9106 i, j, l: Integer;
9107 nPI_l, attenuation: Double;
9108 thesample: single;
9109begin
9110 l := 1024;
9111 nPI_l := 2*PI/l;
9112
9113 for i:=0 to l-1 do
9114 begin
9115 if typewave = 0 then // sine
9116 begin
9117 thesample := sin (i * nPI_l);
9118 if thesample > 1 then
9119 thesample := 1;
9120 if thesample < -1 then
9121 thesample := -1;
9122
9123 if Channel = 1 then
9124 StreamIn[x].Data.LookupTableLeft[i] := thesample;
9125 // writeln ( floattostr ((LookupTableLeft[i])) + ' left ');
9126
9127 if Channel = 2 then
9128 StreamIn[x].Data.LookupTableRight[i] := thesample;
9129 // writeln ( 'right ' + floattostr ((LookupTableRight[i])));
9130
9131 end;
9132
9133 if typewave = 1 then // square
9134 begin
9135 if sin (i * nPI_l) >= 0 then
9136 thesample := 1
9137 else
9138 thesample := -1;
9139
9140 if Channel = 1 then
9141 StreamIn[x].Data.LookupTableLeft[i] := thesample;
9142 if Channel = 2 then
9143 StreamIn[x].Data.LookupTableRight[i] := thesample;
9144 end;
9145
9146 if typewave = 2 then // triangle
9147 begin
9148 if Channel = 1 then
9149 begin
9150 if i < (l div 2) + 1 then
9151 thesample := ( ((l - (i * 2)) / (l / 2))) - 1
9152 else
9153 thesample := StreamIn[x].Data.LookupTableLeft[l - i];
9154 if thesample > 1 then
9155 thesample := 1;
9156 if thesample < -1 then
9157 thesample := -1;
9158 StreamIn[x].Data.LookupTableLeft[i] := thesample;
9159 //writeln ( floattostr ((LookupTableLeft[i])) + ' left ');
9160 end;
9161
9162 if Channel = 2 then
9163 begin
9164 if i < (l div 2) + 1 then
9165 thesample := ( ((l - (i * 2)) / (l / 2))) - 1
9166 else
9167 thesample := StreamIn[x].Data.LookupTableRight[l - i];
9168 if thesample > 1 then
9169 thesample := 1;
9170 if thesample < -1 then
9171 thesample := -1;
9172 StreamIn[x].Data.LookupTableRight[i] := thesample;
9173 // writeln ( floattostr ((LookupTableright[i])) + ' right ');
9174 end;
9175 end;
9176
9177 if typewave = 3 then // Sawtooth
9178 begin
9179 thesample := ( (l - i) / (l / 2)) - 1;
9180 if thesample > 1 then
9181 thesample := 1;
9182 if thesample < -1 then
9183 thesample := -1;
9184
9185 if Channel = 1 then
9186 StreamIn[x].Data.LookupTableLeft[i] := thesample;
9187 if Channel = 2 then
9188 StreamIn[x].Data.LookupTableRight[i] := thesample;
9189 end;
9190 end;
9191
9192 if AHarmonics > 0 then
9193 for j:=1 to AHarmonics do
9194 begin
9195 if ( (( (j mod 2) =1) and (EvenHarmonics=1)) or (EvenHarmonics=0)) then
9196 begin
9197 attenuation := power (j+1, 4);
9198 nPI_l := 2*j*pi/l;
9199 for i:=0 to l-1 do
9200 begin
9201
9202 if typewave = 0 then
9203 begin
9204 if channel = 1 then
9205 StreamIn[x].Data.LookupTableLeft[i] :=
9206 StreamIn[x].Data.LookupTableLeft[i]+sin
9207 (i*nPI_l)/attenuation;
9208 if channel = 2 then
9209 StreamIn[x].Data.LookupTableRight[i] :=
9210 StreamIn[x].Data.LookupTableRight[i]+
9211 sin (i*nPI_l)/attenuation;
9212 end;
9213
9214 if typewave = 1 then
9215 begin
9216 if channel = 1 then
9217 begin
9218 if sin (i*nPI_l) >= 0 then
9219 StreamIn[x].Data.LookupTableLeft[i] :=
9220 StreamIn[x].Data.LookupTableLeft[i]
9221 + (1/attenuation)
9222 else
9223 StreamIn[x].Data.LookupTableLeft[i] :=
9224 StreamIn[x].Data.LookupTableLeft[i]
9225 + (-1/attenuation);
9226 end;
9227 if channel = 2 then
9228 begin
9229 if sin (i*nPI_l) >= 0 then
9230 StreamIn[x].Data.LookupTableRight[i] :=
9231 StreamIn[x].Data.LookupTableRight[
9232 i]+ (1/attenuation)
9233 else
9234 StreamIn[x].Data.LookupTableRight[i] :=
9235 StreamIn[x].Data.LookupTableRight[
9236 i]+ (-1/attenuation);
9237 end;
9238 end;
9239
9240 end;
9241 end;
9242 end;
9243end;
9244
9245procedure Tuos_Player.ReadSynth (x :integer);
9246var
9247 x2 : integer;
9248 sf1, sf2 : cfloat;
9249 ps: PDArShort;
9250 // if input is Int16 format
9251 pl: PDArLong;
9252 // if input is Int32 format
9253 pf: PDArFloat;
9254 // if input is Float32 format
9255
9256 i: culong;
9257 chan : integer;
9258 aFreqL, aFreqR, aPosL, aPosR, aStepL, aStepR: cfloat;
9259
9260begin
9261
9262 //for x2 := 0 to length (StreamIn[x].Data.Buffer)
9263 // do StreamIn[x].Data.Buffer[x2] := 0;
9264
9265 if StreamIn[x].Data.SampleFormat = 2 then ps := @StreamIn[x].Data.Buffer
9266 else
9267 if StreamIn[x].Data.SampleFormat = 1 then pl := @StreamIn[x].Data.Buffer
9268 else
9269 if StreamIn[x].Data.SampleFormat = 0 then pf := @StreamIn[x].Data.Buffer;
9270
9271 chan := StreamIn[x].Data.channels;
9272
9273 aPosL := StreamIn[x].Data.PosInTableLeft;
9274 aPosR := StreamIn[x].Data.PosInTableRight;
9275
9276 aFreqL := StreamIn[x].Data.freqLsine;
9277 aFreqR := StreamIn[x].Data.freqRsine;
9278
9279 aStepL := (aFreqL*1024/StreamIn[x].Data.samplerate);
9280 aStepR := (aFreqR*1024/StreamIn[x].Data.samplerate);;
9281
9282 StreamIn[x].Data.posdursine :=
9283 StreamIn[x].Data.posdursine + (StreamIn[x].Data.WantFrames Div chan);
9284
9285 x2 := 0;
9286
9287 if (StreamIn[x].Data.posdursine <= StreamIn[x].Data.dursine) or (StreamIn[x].Data.dursine = 0)
9288 then
9289 begin
9290
9291 while x2 < (length (StreamIn[x].Data.Buffer) div chan) do
9292 begin
9293
9294 sf2 := 0;
9295 sf1 := 0;
9296
9297 sf1 := StreamIn[x].Data.VLeft*StreamIn[x].Data.LookupTableLeft[trunc (aPosL) And (1023)];
9298 aPosL := aPosL+aStepL;
9299
9300 if chan = 2 then
9301 begin
9302 sf2 := StreamIn[x].Data.VRight*StreamIn[x].Data.LookupTableRight[trunc (aPosR) And (
9303 1023)];
9304 aPosR := aPosR+aStepR;
9305 end;
9306 case StreamIn[x].Data.SampleFormat of
9307 2: // int16
9308 begin
9309 ps^[x2] := trunc (sf1 * 32768);
9310 if chan = 2 then ps^[x2+1] := trunc (sf2 * 32768);
9311 end;
9312 1: // int32
9313 begin
9314 pl^[x2] := trunc (sf1 * 2147483648);
9315 if chan = 2 then pl^[x2+1] := trunc (sf2 * 2147483648);
9316 end;
9317 0: // float32
9318 begin
9319 pf^[x2] := sf1;
9320 if chan = 2 then pf^[x2+1] := sf2;
9321 end;
9322 end;
9323
9324 inc (x2, chan);
9325 end;
9326
9327 i := trunc (aPosL) Div 1024;
9328 StreamIn[x].Data.PosInTableLeft := aPosL- (i*1024);
9329 i := trunc (aPosR) Div 1024;
9330 StreamIn[x].Data.PosInTableRight := aPosR- (i*1024);
9331
9332 StreamIn[x].Data.OutFrames := StreamIn[x].Data.WantFrames;
9333 end
9334 else StreamIn[x].Data.OutFrames := 0;
9335
9336end;
9337{$endif}
9338
9339procedure Tuos_Player.ReadMem(x: integer);
9340var
9341 x2, wantframestemp : integer;
9342{$IF DEFINED (uos_debug) and DEFINED (unix)}
9343 i : integer;
9344 st : string;
9345{$endif}
9346begin
9347 if length (StreamIn[x].Data.memorybuffer) - StreamIn[x].Data.posmem - (StreamIn[x].Data.WantFrames
9348 * StreamIn[x].Data.Channels) >= 0 then wantframestemp := (StreamIn[x].Data.WantFrames
9349 * StreamIn[x].Data.Channels)
9350 else
9351 wantframestemp := length (StreamIn[x].Data.memorybuffer) - StreamIn[x].Data.posmem;
9352
9353{$IF DEFINED (uos_debug) and DEFINED (unix)}
9354 writeln ('length (StreamIn[x].Data.MemoryBuffer) = '+inttostr (length (StreamIn[x].Data.
9355 MemoryBuffer))
9356 );
9357 writeln ('StreamIn[x].Data.posmem = '+inttostr (StreamIn[x].Data.posmem));
9358 writeln ('wantframestemp = '+inttostr (wantframestemp));
9359{$endif}
9360
9361 for x2 := 0 to wantframestemp -1 do
9362 StreamIn[x].Data.Buffer[x2] := (StreamIn[x].Data.memorybuffer[StreamIn[x].Data.posmem + x2]);
9363
9364 StreamIn[x].Data.posmem := StreamIn[x].Data.posmem + wantframestemp;
9365
9366 StreamIn[x].Data.OutFrames := wantframestemp;
9367
9368 if StreamIn[x].Data.SampleFormat > 0 then
9369 StreamIn[x].Data.Buffer := ConvertSampleFormat (StreamIn[x].Data);
9370
9371{$IF DEFINED (uos_debug) and DEFINED (unix)}
9372 writeln ('StreamIn[x].Data.posmem after = '+inttostr (StreamIn[x].Data.posmem));
9373 writeln ('StreamIn[x].Data.OutFrames = '+ inttostr (wantframestemp));
9374 st := '';
9375 for i := 0 to length (StreamIn[x].data.Buffer) -1 do
9376 st := st + '|' + inttostr (i) + '=' + floattostr (StreamIn[x].data.Buffer[i]);
9377 WriteLn ('OUTPUT DATA AFTER Input from memory ------------------------------');
9378 WriteLn (st);
9379{$endif}
9380end;
9381
9382procedure Tuos_Player.ReadMemDec(x: integer);
9383var
9384 wantframestemp : integer;
9385{$IF DEFINED (uos_debug) and DEFINED (unix)}
9386 i : integer;
9387 st : string;
9388{$endif}
9389begin
9390 wantframestemp := (StreamIn[x].Data.WantFrames * StreamIn[x].Data.channels);
9391
9392{$IF DEFINED (uos_debug) and DEFINED (unix)}
9393 writeln ('length (StreamIn[x].MemoryStreamDec) = '+inttostr (StreamIn[x].MemoryStreamDec.size));
9394 writeln ('StreamIn[x].Data.posmem = '+inttostr (StreamIn[x].Data.posmem));
9395 writeln ('wantframestemp = '+inttostr (wantframestemp));
9396{$endif}
9397
9398 StreamIn[x].Data.OutFrames := StreamIn[x].MemoryStreamDec.Read (StreamIn[x].Data.Buffer[0] ,
9399 wantframestemp);
9400
9401 StreamIn[x].Data.OutFrames := StreamIn[x].Data.OutFrames Div StreamIn[x].Data.channels;
9402
9403 StreamIn[x].Data.posmem := StreamIn[x].Data.posmem + wantframestemp;
9404
9405 if StreamIn[x].Data.SampleFormat > 0 then
9406 StreamIn[x].Data.Buffer := ConvertSampleFormat (StreamIn[x].Data);
9407
9408{$IF DEFINED (uos_debug) and DEFINED (unix)}
9409 writeln ('StreamIn[x].Data.posmem after = '+inttostr (StreamIn[x].Data.posmem));
9410 writeln ('StreamIn[x].Data.OutFrames = '+ inttostr (wantframestemp));
9411 st := '';
9412 for i := 0 to length (StreamIn[x].data.Buffer) -1 do
9413 st := st + '|' + inttostr (i) + '=' + floattostr (StreamIn[x].data.Buffer[i]);
9414 WriteLn ('OUTPUT DATA AFTER Input from memory ------------------------------');
9415 WriteLn (st);
9416{$endif}
9417end;
9418
9419procedure Tuos_Player.DoSeek ( x : integer);
9420begin
9421 if StreamIn[x].Data.TypePut = 4 then
9422 StreamIn[x].Data.posmem := 0
9423 else
9424
9425 case StreamIn[x].Data.LibOpen of
9426 -1:;
9427 {$IF DEFINED (sndfile)}
9428 0: sf_seek (StreamIn[x].Data.HandleSt, StreamIn[x].Data.Poseek, 0);
9429 {$endif}
9430 {$IF DEFINED (mpg123)}
9431 1: mpg123_seek (StreamIn[x].Data.HandleSt, StreamIn[x].Data.Poseek, 0);
9432 {$endif}
9433 {$IF DEFINED (neaac)}
9434 2 : MP4Seek (StreamIn[x].AACI, StreamIn[x].Data.Poseek);
9435 {$endif}
9436 {$IF DEFINED (cdrom)}
9437 3 :;
9438 {$endif}
9439 {$IF DEFINED (opus)}
9440 4 : op_pcm_seek (StreamIn[x].Data.HandleOP, StreamIn[x].Data.Poseek);
9441 {$endif}
9442 {$IF DEFINED (xmp)}
9443 5 : xmp_seek_time(StreamIn[x].Data.HandleSt,round(StreamIn[x].Data.Poseek / (StreamIn[x].Data.
9444 samplerate / 1000)));
9445 {$endif}
9446 end;
9447end;
9448
9449procedure Tuos_Player.DoDSPOutAfterBufProc (x: integer);
9450var
9451 x3 : integer;
9452{$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
9453 msg: TfpgMessageParams;
9454 // for fpgui
9455 {$endif}
9456begin
9457
9458 for x3 := 0 to high (StreamOut[x].DSP) do
9459 if (StreamOut[x].DSP[x3].Enabled = True) then
9460 begin
9461 if (StreamOut[x].DSP[x3].AftFunc <> nil) then
9462 StreamOut[x].Data.Buffer :=
9463 StreamOut[x].DSP[x3].AftFunc (StreamOut[x].Data,
9464 StreamOut[x].DSP[x3].fftdata);
9465
9466 {$IF DEFINED (mse)}
9467 if (StreamOut[x].DSP[x3].LoopProc <> nil) then
9468 begin
9469 application.queueasynccall (StreamOut[x].DSP[x3].LoopProc);
9470 end;
9471 {$else}
9472
9473 {$IF not DEFINED (Library)}
9474 if (StreamOut[x].DSP[x3].LoopProc <> nil) then
9475 {$IF FPC_FULLVERSION>=20701}
9476 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,StreamOut[x].
9477 DSP[x3].LoopProc);
9478 {$else}
9479 {$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
9480 begin
9481 msg.user.Param1 := x3;
9482 // the index of the dsp
9483 msg.user.Param2 := 1;
9484 // it is an OUT DSP
9485 fpgPostMessage (self, refer, MSG_CUSTOM1, msg);
9486 end;
9487 {$else}
9488 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,StreamOut[x].
9489 DSP[
9490 x3].LoopProc);
9491 {$endif}
9492 {$endif}
9493
9494 {$elseif not DEFINED (java)}
9495 if (StreamOut[x].DSP[x3].LoopProc <> nil) then
9496 StreamOut[x].DSP[x3].LoopProc;
9497 {$else}
9498 if (StreamOut[x].DSP[x3].LoopProc <> nil) then
9499 {$IF FPC_FULLVERSION >= 20701}
9500 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@StreamOut[x]
9501 .
9502 DSP[x3].LoopProcjava);
9503 {$else}
9504 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@StreamOut[x].
9505 DSP
9506 [x3].LoopProcjava);
9507 {$endif}
9508 {$endif}
9509
9510 {$endif}
9511 end;
9512end;
9513
9514procedure Tuos_Player.DoArrayLevel (x: integer);
9515begin
9516 setlength (uosLevelArray[index][x],length (uosLevelArray[index][x]) +1);
9517 uosLevelArray[index][x][length (uosLevelArray[index][x]) -1 ] := StreamIn[x].Data.LevelLeft;
9518
9519 setlength (uosLevelArray[index][x],length (uosLevelArray[index][x]) +1);
9520 uosLevelArray[index][x][length (uosLevelArray[index][x]) -1 ] := StreamIn[x].Data.LevelRight;
9521
9522 // writeln ('array length = ' + inttostr (length (uosLevelArray[index][x])));
9523end;
9524
9525{$IF DEFINED (portaudio)}
9526procedure Tuos_Player.ReadDevice (x : integer);
9527var
9528 x2 : integer;
9529begin
9530 for x2 := 0 to StreamIn[x].Data.WantFrames -1 do
9531 StreamIn[x].Data.Buffer[x2] := cfloat (0.0);
9532 // clear input
9533 Pa_ReadStream (StreamIn[x].Data.HandleSt,
9534 @StreamIn[x].Data.Buffer[0], StreamIn[x].Data.WantFrames);
9535
9536 // err :=// if you want clean buffer
9537 StreamIn[x].Data.OutFrames :=
9538 StreamIn[x].Data.WantFrames * StreamIn[x].Data.Channels;
9539
9540// if err = 0 then StreamIn[x].Data.Status := 1 else StreamIn[x].Data.Status := 0;// if you want clean buffer
9541end;
9542{$endif}
9543
9544procedure Tuos_Player.DoDSPinBeforeBufProc (x: integer);
9545var
9546 x2 : integer;
9547begin
9548 for x2 := 0 to high (StreamIn[x].DSP) do
9549 if (StreamIn[x].DSP[x2].Enabled = True) and
9550 (StreamIn[x].DSP[x2].BefFunc <> nil) then
9551 StreamIn[x].DSP[x2].BefFunc (StreamIn[x].Data, StreamIn[x].DSP[x2].fftdata);
9552end;
9553
9554procedure Tuos_Player.DoDSPinAfterBufProc (x: integer);
9555var
9556 x2 : integer;
9557{$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
9558 msg: TfpgMessageParams;
9559 // for fpgui
9560 {$endif}
9561begin
9562 for x2 := 0 to high (StreamIn[x].DSP) do
9563 if (StreamIn[x].DSP[x2].Enabled = True) then
9564 begin
9565
9566 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9567 writeln ('DSPin AfterBuffProc 1.');
9568 {$endif}
9569 if (StreamIn[x].DSP[x2].AftFunc <> nil) then
9570 StreamIn[x].Data.Buffer :=
9571 StreamIn[x].DSP[x2].AftFunc (StreamIn[x].Data,
9572 StreamIn[x].DSP[x2].fftdata);
9573
9574 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9575 writeln ('DSPin AfterBuffProc 2.');
9576 {$endif}
9577
9578 {$IF DEFINED (mse)}
9579 if (StreamIn[x].DSP[x2].LoopProc <> nil) then
9580 begin
9581 application.queueasynccall (StreamIn[x].DSP[x2].LoopProc);
9582 end;
9583 {$else}
9584
9585 {$IF not DEFINED (Library)}
9586 if (StreamIn[x].DSP[x2].LoopProc <> nil) then
9587 {$IF FPC_FULLVERSION>=20701}
9588 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,StreamIn[x].
9589 DSP
9590 [x2].LoopProc);
9591 {$else}
9592 {$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
9593 begin
9594 msg.user.Param1 := x2;
9595 // the index of the dsp
9596 msg.user.Param2 := 0;
9597 // it is an In DSP
9598 fpgPostMessage (self, refer, MSG_CUSTOM1, msg);
9599 end;
9600 {$else}
9601 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,StreamIn[x].DSP[x2].LoopProc);
9602 {$endif}
9603 {$endif}
9604 {$elseif not DEFINED (java)}
9605 if (StreamIn[x].DSP[x2].LoopProc <> nil) then
9606 StreamIn[x].DSP[x2].LoopProc;
9607 {$else}
9608 if (StreamIn[x].DSP[x2].LoopProc <> nil) then
9609 {$IF FPC_FULLVERSION>=20701}
9610 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@Streamin[x].DSP[x2].LoopProcjava);
9611 {$else}
9612 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@Streamin[x].DSP[x2].LoopProcjava);
9613 {$endif}
9614 {$endif}
9615 {$endif}
9616 end;
9617end;
9618
9619procedure Tuos_Player.SeekIfTerminated;
9620var
9621 x, statustemp : integer;
9622begin
9623
9624 statustemp := 0;
9625 for x := 0 to high (StreamIn) do
9626 begin
9627 if (StreamIn[x].Data.enabled = true)
9628 then
9629 begin
9630
9631 if (StreamIn[x].Data.TypePut <> 1)
9632 then
9633 begin
9634 if StreamIn[x].Data.Status = 1 then
9635 statustemp := StreamIn[x].Data.Status;
9636 if (StreamIn[x].Data.Status = 2) and (statustemp = 0) then
9637 statustemp := StreamIn[x].Data.Status;
9638 end
9639 else
9640 if
9641 (StreamIn[x].Data.TypePut = 1) then statustemp := status;
9642 end;
9643 end;
9644
9645 if statustemp <> status then status := statustemp;
9646
9647 if (status = 0) and IsLooped then
9648 begin
9649 for x:= 0 to high (StreamIn) do
9650 begin
9651 InputSeek (x, 0);
9652 if StreamIn[x].Data.TypePut = 4 then
9653 StreamIn[x].Data.posmem := 0;
9654 StreamIn[x].Data.status := 1;
9655 end;
9656
9657 Status := 1;
9658
9659 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9660 WriteLn ('Loop (NLooped: '+IntToStr (NLooped)+')----');
9661 {$endif}
9662
9663 if NLooped > 0 then
9664 Dec (NLooped);
9665 end;
9666end;
9667
9668procedure Tuos_Player.DoLoopEndMethods;
9669begin
9670{$IF DEFINED (mse)}
9671 if LoopEndProc <> nil then
9672 begin
9673 application.queueasynccall (LoopEndProc);
9674 end;
9675 {$else}
9676
9677 {$IF not DEFINED (Library)}
9678 if LoopEndProc <> nil then
9679
9680 // Execute LoopEndProc procedure
9681 {$IF FPC_FULLVERSION>=20701}
9682 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,LoopEndProc);
9683 {$else}
9684 {$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
9685 begin
9686 msg.user.Param1 := -2;
9687 // it is the first proc
9688 fpgPostMessage (self, refer, MSG_CUSTOM1, msg);
9689 end;
9690 {$else}
9691 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,LoopEndProc);
9692 {$endif}
9693 {$endif}
9694 {$elseif not DEFINED (java)}
9695 if LoopEndProc <> nil then LoopEndProc;
9696 {$else}
9697 if LoopEndProc <> nil then
9698 {$IF FPC_FULLVERSION>=20701}
9699 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@endprocjava);
9700 {$else}
9701 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@endprocjava);
9702 // Execute EndProc procedure
9703 {$endif}
9704 {$endif}
9705 {$endif}
9706end;
9707
9708procedure Tuos_Player.DoEndProc;
9709begin
9710{$IF DEFINED (mse)}
9711 if EndProc <> nil then
9712 application.queueasynccall (EndProc);
9713 {$else}
9714
9715 {$IF not DEFINED (Library)}
9716 if EndProc <> nil then
9717 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread, @EndProcExecute);
9718
9719 {$elseif not DEFINED (java)}
9720 if (EndProc <> nil) then
9721 EndProc;
9722 {$else}
9723 if (EndProc <> nil) then
9724 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@endprocjava);
9725 {$endif}
9726 {$endif}
9727end;
9728
9729procedure Tuos_Player.EndProcExecute;
9730begin
9731 EndProc(Index);
9732end;
9733
9734procedure Tuos_Player.DoTerminateNoFreePlayer;
9735var
9736 x, x2 : integer;
9737begin
9738
9739 for x := 0 to high (StreamIn) do
9740 begin
9741 if (length (StreamIn[x].DSP) > 0) then
9742 for x2 := 0 to high (StreamIn[x].DSP) do
9743 if (StreamIn[x].DSP[x2].EndFunc <> nil) then
9744 StreamIn[x].DSP[x2].EndFunc (StreamIn[x].Data, StreamIn[x].DSP[x2].fftdata);
9745 end;
9746
9747 for x := 0 to high (StreamOut) do
9748 begin
9749 if (length (StreamOut[x].DSP) > 0) then
9750 for x2 := 0 to high (StreamOut[x].DSP) do
9751 if (StreamOut[x].DSP[x2].EndFunc <> nil) then
9752 StreamOut[x].DSP[x2].EndFunc (StreamOut[x].Data, StreamOut[x].DSP[x2].fftdata);
9753 end;
9754
9755 if (StreamOut[x].Data.TypePut = 0) then
9756 begin
9757 WriteWave (StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
9758 // StreamOut[x].FileBuffer.Data.Free;
9759 end;
9760
9761 if (StreamOut[x].Data.TypePut = 4) then
9762 begin
9763 WriteWaveFromMem (StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
9764 // StreamOut[x].FileBuffer.Data.Free;
9765 end;
9766
9767 {$IF DEFINED (sndfile)}
9768 if (StreamOut[x].Data.TypePut = 6) then
9769 begin
9770 sf_write_sync (StreamOut[x].Data.HandleSt);
9771 sf_close (StreamOut[x].Data.HandleSt);
9772 end;
9773
9774 if (StreamOut[x].Data.TypePut = 5) then
9775 begin
9776 sf_write_sync (StreamOut[x].Data.HandleSt);
9777 sf_close (StreamOut[x].Data.HandleSt);
9778 end;
9779 {$endif}
9780
9781 {$IF DEFINED (mse)}
9782 if EndProc <> nil then
9783 begin
9784 application.queueasynccall (EndProc);
9785 end;
9786 {$else}
9787
9788 {$IF not DEFINED (Library)}
9789 if EndProc <> nil then
9790 {$IF FPC_FULLVERSION>=20701}
9791 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread, @EndProcExecute);
9792 {$else}
9793 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,EndProc);
9794 // Execute EndProc procedure
9795 {$endif}
9796
9797 {$elseif not DEFINED (java)}
9798 if (EndProc <> nil) then
9799 EndProc;
9800 {$else}
9801 if (EndProc <> nil) then
9802 {$IF FPC_FULLVERSION>=20701}
9803 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@endprocjava);
9804 {$else}
9805 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@endprocjava);
9806 // Execute EndProc procedure
9807 {$endif}
9808
9809 {$endif}
9810 {$endif}
9811
9812 {$IF DEFINED (portaudio)}
9813 for x := 0 to high (StreamOut) do
9814 if (StreamOut[x].Data.HandleSt <> nil) and
9815 (StreamOut[x].Data.TypePut = 1) then
9816 Pa_StopStream (StreamOut[x].Data.HandleSt);
9817 {$ENDIF}
9818
9819 if EndProcOnly <> nil then EndProcOnly;
9820
9821 StreamIn[x].Data.Poseek := 0;
9822 // set to begin
9823 doseek (x);
9824
9825 Status := 2;
9826
9827 if isGlobalPause = true then
9828 begin
9829 RTLeventReSetEvent (uosInit.evGlobalPause)
9830 end
9831 else
9832 begin
9833 RTLeventReSetEvent (evPause);
9834 end;
9835end;
9836
9837procedure Tuos_Player.DoTerminatePlayer;
9838var
9839 x, x2 : integer;
9840begin
9841
9842 if length (PlugIn) > 0 then
9843 begin
9844 for x := 0 to high (PlugIn) do
9845 begin
9846 {$IF DEFINED (soundtouch)}
9847 if Plugin[x].Name = 'soundtouch' then
9848 begin
9849 soundtouch_clear (Plugin[x].PlugHandle);
9850 soundtouch_destroyInstance (Plugin[x].PlugHandle);
9851 end;
9852
9853 if Plugin[x].Name = 'getbpm' then
9854 begin
9855 bpm_destroyInstance (Plugin[x].PlugHandle);
9856 end;
9857 {$endif}
9858
9859 {$IF DEFINED (bs2b)}
9860 if Plugin[x].Name = 'bs2b' then
9861 begin
9862 bs2b_close (Plugin[x].Abs2b);
9863 end;
9864 {$endif}
9865 end;
9866 end;
9867
9868 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9869 writeln ('Destroy DSP In');
9870 {$endif}
9871
9872 for x := 0 to high (StreamIn) do
9873 begin
9874 if (length (StreamIn[x].DSP) > 0) then
9875 for x2 := 0 to high (StreamIn[x].DSP) do
9876 if (StreamIn[x].DSP[x2].EndFunc <> nil) then
9877 StreamIn[x].DSP[x2].EndFunc (StreamIn[x].Data, StreamIn[x].DSP[x2].fftdata);
9878 end;
9879
9880 {$IF DEFINED (uos_debug) and DEFINED (unix)}
9881 writeln ('Destroy DSP Out');
9882 {$endif}
9883
9884 for x := 0 to high (StreamOut) do
9885 begin
9886 if (assigned (StreamOut[x].DSP)) and
9887 (assigned (StreamOut[x])) then
9888 if (length (StreamOut[x]
9889 .
9890 DSP) > 0) then
9891 for x2 := 0 to high (StreamOut[x].DSP) do
9892 if (StreamOut[x].DSP[x2].EndFunc <>nil)
9893 then
9894 StreamOut[x].DSP[x2].EndFunc(StreamOut[x].Data, StreamOut[x].DSP[x2].fftdata);
9895 end;
9896
9897 for x := 0 to high (StreamIn) do
9898 if assigned (StreamIn[x].Data.HandleSt) then if (StreamIn[x].Data.HandleSt <> nil) then
9899 case StreamIn[x].Data.TypePut of
9900 0: case StreamIn[x].Data.LibOpen of
9901 {$IF DEFINED (sndfile)}
9902 0: sf_close (StreamIn[x].Data.HandleSt);
9903 {$endif}
9904 {$IF DEFINED (mpg123)}
9905 1:
9906 begin
9907 mpg123_close (StreamIn[x].Data.
9908 HandleSt
9909 );
9910 mpg123_delete (StreamIn[x].Data.
9911 HandleSt);
9912 end;
9913 {$ENDIF}
9914 {$IF DEFINED (neaac)}
9915 2 :
9916 begin
9917 MP4CloseFile (StreamIn[x].AACI);
9918 end;
9919 {$endif}
9920 {$IF DEFINED (cdrom)}
9921 3:
9922 begin
9923 CDROM_Close (StreamIn[x].pCD);
9924 end;
9925 {$endif}
9926 {$IF DEFINED (opus)}
9927 4:
9928 begin
9929 op_free (StreamIn[x].Data.HandleOP);
9930 sleep (50);
9931 // needed ?
9932 end;
9933 {$ENDIF}
9934 {$IF DEFINED (xmp)}
9935 5:
9936 begin
9937 xmp_end_player (StreamIn[x].Data.
9938 HandleSt);
9939 xmp_release_module (StreamIn[x].Data.
9940 HandleSt);
9941 xmp_free_context (StreamIn[x].Data.
9942 HandleSt);
9943 end;
9944 {$ENDIF}
9945
9946 99: // if nothing was defined
9947
9948 end;
9949
9950 {$IF DEFINED (portaudio)}
9951 1:
9952 begin
9953 Pa_StopStream (StreamIn[x].Data.HandleSt);
9954 Pa_CloseStream (StreamIn[x].Data.HandleSt)
9955 ;
9956 end;
9957 {$endif}
9958 {$IF DEFINED (webstream)}
9959 2:
9960 begin
9961 StreamIn[x].httpget.Terminate;
9962 sleep (100);
9963 StreamIn[x].inpipe.destroy;
9964 StreamIn[x].outpipe.destroy;
9965
9966 case StreamIn[x].Data.LibOpen of
9967 {$IF DEFINED (mpg123)}
9968 1:
9969 begin
9970 mpg123_close (StreamIn[x].Data.
9971 HandleSt);
9972 mpg123_delete (StreamIn[x].Data.
9973 HandleSt);
9974 end;
9975 {$ENDIF}
9976 {$IF DEFINED (opus)}
9977 4:
9978 begin
9979 op_free (StreamIn[x].Data.HandleOP)
9980 ;
9981 sleep (50);
9982 // needed ?
9983 end;
9984 {$ENDIF}
9985 {$IF DEFINED (fdkaac)}
9986 2 :
9987 begin
9988 aacDecoder_Close (StreamIn[x].Data
9989 .HandleSt);
9990 end;
9991 {$ENDIF}
9992 end;
9993 end;
9994 {$ENDIF}
9995
9996 end;
9997
9998 for x := 0 to high (StreamOut) do
9999 begin
10000 {$IF DEFINED (portaudio)}
10001 if (StreamOut[x].Data.HandleSt <> nil) and
10002 (StreamOut[x].Data.TypePut = 1) then
10003 begin
10004 Pa_StopStream (StreamOut[x].Data.HandleSt);
10005 Pa_CloseStream (StreamOut[x].Data.HandleSt);
10006 end;
10007 {$ENDIF}
10008
10009 {$IF DEFINED (shout)}
10010 if (StreamOut[x].Data.TypePut = 2) then
10011 begin
10012 // freeandnil (StreamOut[x].encoder);
10013 shout_free (StreamOut[x].Data.HandleSt);
10014
10015 end;
10016 {$endif}
10017
10018 if (StreamOut[x].Data.TypePut = 0) then
10019 begin
10020 WriteWave (StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
10021 // StreamOut[x].FileBuffer.Data.Free;
10022 end;
10023
10024 if (StreamOut[x].Data.TypePut = 4) then
10025 begin
10026 WriteWaveFromMem (StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
10027 StreamOut[x].FileBuffer.Data.Free;
10028 end;
10029
10030 {$IF DEFINED (sndfile)}
10031
10032 if (StreamOut[x].Data.TypePut = 6) then
10033 begin
10034 sf_close ( StreamOut[x].Data.HandleSt);
10035 end;
10036
10037 if (StreamOut[x].Data.TypePut = 7) then
10038 begin
10039 sf_close ( StreamOut[x].Data.HandleSt);
10040 end;
10041 {$endif}
10042
10043 end;
10044end;
10045
10046procedure Tuos_Player.DoMainLoopProc (x: integer);
10047{$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
10048var
10049 msg: TfpgMessageParams;
10050 // for fpgui
10051{$endif}
10052begin
10053
10054 {$IF DEFINED (mse)}
10055 if StreamIn[x].LoopProc <> nil then
10056 begin
10057 application.queueasynccall (StreamIn[x].LoopProc);
10058 end;
10059 {$else}
10060 // The synchro main loop procedure
10061 {$IF not DEFINED (Library)}
10062 if StreamIn[x].LoopProc <> nil then
10063 {$IF FPC_FULLVERSION>=20701}
10064 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,StreamIn[x].LoopProc);
10065 {$else}
10066 {$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
10067 begin
10068 msg.user.Param1 := -1;
10069 // it is the main loop procedure
10070 msg.user.Param2 := 0;
10071 // it is an INput procedure
10072 fpgPostMessage (self, refer, MSG_CUSTOM1, msg);
10073 end;
10074 {$else}
10075 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,StreamIn[x].LoopProc);
10076 {$endif}
10077 {$endif}
10078
10079 {$elseif not DEFINED (java)}
10080 if (StreamIn[x].LoopProc <> nil) then
10081 StreamIn[x].LoopProc;
10082 {$else}
10083 if (StreamIn[x].LoopProc <> nil) then
10084 {$IF FPC_FULLVERSION>=20701}
10085 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@Streamin[x].LoopProcjava);
10086 {$else}
10087 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@Streamin[x].LoopProcjava);
10088 {$endif}
10089 {$endif}
10090 {$endif}
10091end;
10092
10093procedure Tuos_Player.DoBeginMethods;
10094{$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
10095var
10096 msg: TfpgMessageParams;
10097 // for fpgui
10098 {$endif}
10099begin
10100{$IF DEFINED (mse)}
10101 if BeginProc <> nil then
10102 begin
10103 application.queueasynccall (BeginProc);
10104 end;
10105 {$else}
10106
10107 {$IF not DEFINED (Library)}
10108 if BeginProc <> nil then
10109 // Execute BeginProc procedure
10110 {$IF FPC_FULLVERSION>=20701}
10111 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,BeginProc);
10112 {$else}
10113 {$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
10114 begin
10115 msg.user.Param1 := -2;
10116 // it is the first proc
10117 fpgPostMessage (self, refer, MSG_CUSTOM1, msg);
10118 end;
10119 {$else}
10120 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,BeginProc);
10121 {$endif}
10122 {$endif}
10123 {$elseif not DEFINED (java)}
10124 if BeginProc <> nil then
10125 BeginProc;
10126 {$else}
10127 if BeginProc <> nil then
10128 {$IF FPC_FULLVERSION>=20701}
10129 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@BeginProcjava);
10130 {$else}
10131 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@BeginProcjava);
10132 {$endif}
10133 {$endif}
10134 {$endif}
10135end;
10136
10137procedure Tuos_Player.DoLoopBeginMethods;
10138{$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
10139var
10140 msg: TfpgMessageParams;
10141 // for fpgui
10142 {$endif}
10143begin
10144{$IF DEFINED (mse)}
10145 if LoopBeginProc <> nil then
10146 begin
10147 application.queueasynccall (LoopBeginProc);
10148 end;
10149 {$else}
10150 {$IF not DEFINED (Library)}
10151 if LoopBeginProc <> nil then
10152 // Execute BeginProc procedure
10153 {$IF FPC_FULLVERSION>=20701}
10154 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,LoopBeginProc);
10155 {$else}
10156 {$IF (FPC_FULLVERSION < 20701) and DEFINED (fpgui)}
10157 begin
10158 msg.user.Param1 := -2;
10159 // it is the first proc
10160 fpgPostMessage (self, refer, MSG_CUSTOM1, msg);
10161 end;
10162 {$else}
10163 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,LoopBeginProc);
10164 {$endif}
10165 {$endif}
10166 {$elseif not DEFINED (java)}
10167 if loopBeginProc <> nil then
10168 loopBeginProc;
10169 {$else}
10170 if loopBeginProc <> nil then
10171 {$IF FPC_FULLVERSION>=20701}
10172 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@loopBeginProcjava);
10173 {$else}
10174 thethread.{$IF DEFINED (usequeue)}Queue{$else}Synchronize{$endif} (thethread,@loopBeginProcjava);
10175 {$endif}
10176 {$endif}
10177 {$endif}
10178end;
10179
10180procedure Tuos_Player.WriteOut (x:integer; x2 : integer);
10181var
10182 err, rat, wantframestemp: integer;
10183
10184{$IF DEFINED (uos_debug) and DEFINED (unix)}
10185 st : string;
10186 i : integer;
10187{$endif}
10188 BufferCv: TDArFloat;
10189begin
10190 // Convert Input format into Output format if needed:
10191 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10192 writeln ('Convert Input format into Output');
10193 {$endif}
10194 case StreamOut[x].Data.SampleFormat of
10195 0: case StreamIn[x2].Data.SampleFormat of
10196 1: StreamOut[x].Data.Buffer :=
10197 CvInt32toFloat32 (StreamOut[x].Data.Buffer);
10198 2: StreamOut[x].Data.Buffer :=
10199 CvInt16toFloat32 (StreamOut[x].Data.Buffer);
10200 end;
10201 end;
10202 // End convert.
10203 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10204 writeln ('Finally give buffer to output');
10205 {$endif}
10206
10207 // Finally give buffer to output
10208 case StreamOut[x].Data.TypePut of
10209 {$IF DEFINED (portaudio)}
10210 1: // Give to output device using portaudio
10211 begin
10212
10213 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10214 writeln ('Give to output device');
10215 writeln ('length (StreamOut[x].Data.Buffer) =' + inttostr (length (StreamOut[x].Data.Buffer
10216 )));
10217 {$endif}
10218
10219 if (StreamIn[x2].Data.TypePut <> 1) or
10220 ( (StreamIn[x2].Data.TypePut = 1) and (StreamIn[x2].Data.Channels > 1)) then
10221 begin
10222 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10223 st := '';
10224 for i := 0 to length (StreamOut[x].Data.Buffer) -1 do
10225 st := st + '|' + inttostr (i) + '=' + floattostr (StreamOut[x].Data.Buffer[i]);
10226 WriteLn ('OUTPUT DATA into portaudio------------------------------');
10227 //WriteLn (st);
10228 {$endif}
10229
10230 // err :=// if you want clean buffer
10231
10232 if assigned (StreamOut[x].Data.HandleSt) then
10233 Pa_WriteStream (StreamOut[x].Data.HandleSt,
10234 @StreamOut[x].Data.Buffer[0], StreamIn[x2].Data.outframes Div
10235 StreamIn
10236 [x2].Data.ratio);
10237
10238 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10239 writeln ('give to output device 1');
10240{$endif}
10241 end
10242 else
10243 begin
10244 // err :=// if you want clean buffer
10245 Pa_WriteStream (StreamOut[x].Data.HandleSt,
10246 @StreamOut[x].Data.Buffer[0], StreamIn[x2].Data.outframes);
10247 end;
10248 // if err <> 0 then status := 0;// if you want clean buffer ...
10249{$IF DEFINED (uos_debug) and DEFINED (unix)}
10250 writeln ('End give to output device 2');
10251{$endif}
10252 end;
10253{$endif}
10254
10255 {$IF DEFINED (shout)}
10256 2: // Give to IceCast server
10257 begin
10258
10259{$IF DEFINED (uos_debug) and DEFINED (unix)}
10260 writeln ('Give to output IceCast server');
10261{$endif}
10262
10263 case StreamOut[x].Data.SampleFormat of
10264 0:
10265 begin
10266 err := opus_encode_float (StreamOut[x].encoder, @StreamOut[x].Data.Buffer[0],
10267 cFRAME_SIZE*3, StreamOut[x].cbits, cMAX_PACKET_SIZE);
10268 end;
10269 1:
10270 begin
10271 err := opus_encode (StreamOut[x].encoder, @StreamOut[x].Data.Buffer[0], cFRAME_SIZE
10272 *
10273 3, StreamOut[x].cbits, cMAX_PACKET_SIZE);
10274 end;
10275 2:
10276 begin
10277 err := opus_encode (StreamOut[x].encoder, @StreamOut[x].Data.Buffer[0], cFRAME_SIZE*
10278 3
10279 , StreamOut[x].cbits, cMAX_PACKET_SIZE);
10280 end;
10281 end;
10282
10283 StreamOut[x].data.outframes := err;
10284
10285{$IF DEFINED (uos_debug) and DEFINED (unix)}
10286 WriteLn ('opus_encode outframes =' + inttostr (err));
10287 WriteLn ('----------------------------------');
10288 // writeln (tencoding.utf8.getstring (StreamOut[x].cbits));
10289 {$endif}
10290
10291 if err > 0 then
10292
10293 err := shout_send_raw (StreamOut[x].Data.HandleSt, StreamOut[x].cbits, StreamOut[x].data.
10294 outframes);
10295
10296{$IF DEFINED (uos_debug) and DEFINED (unix)}
10297 if err = SHOUTERR_SUCCESS then
10298 WriteLn ('shout_send ok ' + inttostr (err))
10299 else
10300 WriteLn ('shout_send error: '+ inttostr (err) + ' ' + pchar (shout_get_error (StreamOut[x
10301 ].
10302 Data.HandleSt)));
10303 writeln ('End give output to IceCast server');
10304 {$endif}
10305
10306 shout_sync (StreamOut[x].Data.HandleSt);
10307 end;
10308 {$endif}
10309
10310 3:
10311 begin
10312 // Give to memory buffer
10313
10314 wantframestemp := StreamIn[x2].Data.outframes;
10315
10316 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10317 WriteLn ('Before Give to memory ------------------------------');
10318 st := '';
10319 for i := 0 to wantframestemp -1 do
10320 st := st + '|' + inttostr (i) + '=' + floattostr (StreamOut[x].Data.Buffer[i]);
10321 WriteLn (st);
10322 WriteLn ('OUTPUT DATA AFTER5 ------------------------------');
10323 writeln ('Streamout[x].Data.posmem before = '+inttostr ( Streamout[x].Data.posmem));
10324
10325 writeln ('StreamIn[x2].Data.outframes * StreamIn[x2].Data.channels = '+inttostr ( StreamIn[
10326 x2
10327 ].Data.outframes * StreamIn[x2].Data.channels));
10328 writeln ('length (tempoutmemory) = '+ inttostr (length (tempoutmemory)));
10329 writeln ('Begin Give to memory buffer');
10330 writeln (' (StreamIn[x2].Data.outframes ) -1 = ' +
10331 inttostr ((StreamIn[x2].Data.outframes) -1));
10332 {$endif}
10333
10334 if StreamIn[x2].Data.numbuf > -1 then
10335 begin
10336 // writeln ('theinc = ' + inttostr (theinc));
10337 inc (theinc);
10338 if theinc > StreamIn[x2].Data.numbuf then status := 0;
10339 end;
10340
10341 SetLength (Streamout[x].BufferOut^,length (Streamout[x].BufferOut^) + wantframestemp );
10342
10343 Streamout[x].Data.posmem := length (Streamout[x].BufferOut^) - wantframestemp;
10344
10345 for x2 := 0 to (wantframestemp) -1 do
10346 begin
10347 Streamout[x].BufferOut^[Streamout[x].Data.posmem + x2] := StreamOut[x].Data.Buffer[x2];
10348 end;
10349 Streamout[x].Data.posmem := Streamout[x].Data.posmem + (wantframestemp);
10350
10351 // if Streamout[x].Data.SampleFormat > 0 then
10352 //StreamOut[x].Data.Buffer := ConvertSampleFormat (StreamOut[x].Data);
10353
10354 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10355 writeln ('Streamout[x].Data.posmem after = '+inttostr ( Streamout[x].Data.posmem));
10356 st := '';
10357 for i := 0 to length (tempoutmemory) -1 do
10358 st := st + '|' + inttostr (i) + '=' + floattostr (tempoutmemory[i]);
10359 WriteLn ('OUTPUT DATA AFTER5 ------------------------------');
10360 //WriteLn (st);
10361 {$endif}
10362
10363 end;
10364
10365 4: // Give to wav file from TMemoryStream
10366 begin
10367
10368 case StreamOut[x].Data.SampleFormat of
10369 0: rat := 2;
10370 1: rat := 2;
10371 2: rat := 1;
10372 end;
10373
10374 if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
10375 begin
10376
10377 BufferCv := CvStereoToMono (StreamOut[x].Data.Buffer, StreamIn[x2].Data.outframes);
10378
10379 StreamOut[x].FileBuffer.DataMS.WriteBuffer (
10380 BufferCv[0],
10381 StreamIn[x2].Data.outframes * rat);
10382 end
10383 else
10384 if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 1) then
10385 begin
10386 StreamOut[x].FileBuffer.DataMS.WriteBuffer (
10387 StreamOut[x].Data.Buffer[0],
10388 StreamIn[x2].Data.outframes * StreamIn[x2].Data.ratio * rat * 2);
10389 end
10390 else
10391 StreamOut[x].FileBuffer.DataMS.WriteBuffer (
10392 StreamOut[x].Data.Buffer[0],
10393 StreamIn[x2].Data.outframes * StreamIn[x2].Data.Channels * rat);
10394 end;
10395
10396 {$IF DEFINED (sndfile)}
10397 5: // Give to MemoryStream
10398 begin
10399
10400 if StreamIn[x2].Data.TypePut = 1 then rat := StreamIn[x2].Data.Channels
10401 else rat := 1;
10402
10403 // writeln ('MemoryStream');
10404
10405 if assigned (StreamOut[x].MemorySteamOut) then
10406
10407 case StreamOut[x].Data.SampleFormat of
10408
10409 0: StreamOut[x].Data.OutFrames :=
10410 sf_write_float (StreamOut[x].Data.HandleSt,
10411 @StreamOut[x].Data.Buffer[0], StreamOut[x].Data.Wantframes *rat );
10412 1: StreamOut[x].Data.OutFrames :=
10413 sf_write_int (StreamOut[x].Data.HandleSt,
10414 @StreamOut[x].Data.Buffer[0], StreamOut[x].Data.Wantframes *rat );
10415 2: StreamOut[x].Data.OutFrames :=
10416 sf_write_short (StreamOut[x].Data.HandleSt,
10417 @StreamOut[x].Data.Buffer[0], StreamOut[x].Data.Wantframes *rat);
10418 end;
10419 end;
10420
10421 6: // give to ogg file from Tfilestream
10422 begin
10423 //writeln ('ok ogg');
10424
10425 if (StreamOut[x].Data.channels = 1) and (StreamIn[x2].Data.Channels = 2) then
10426 begin
10427 BufferCv := CvStereoToMono(StreamOut[x].Data.Buffer, StreamIn[x2].Data.outframes);
10428 case StreamOut[x].Data.SampleFormat of
10429 0: StreamOut[x].Data.OutFrames :=
10430 sf_write_float(StreamOut[x].Data.HandleSt,
10431 @BufferCv[0], StreamIn[x2].Data.outframes Div 2);
10432 1: StreamOut[x].Data.OutFrames :=
10433 sf_write_int(StreamOut[x].Data.HandleSt,
10434 @BufferCv[0], StreamIn[x2].Data.outframes Div 2);
10435 2: StreamOut[x].Data.OutFrames :=
10436 sf_write_short(StreamOut[x].Data.HandleSt,
10437 @BufferCv[0], StreamIn[x2].Data.outframes Div 2);
10438 end;
10439 end
10440 else
10441 if (StreamOut[x].Data.channels = 2) and (StreamIn[x2].Data.Channels = 1) then
10442 begin
10443 BufferCv := CvMonoToStereo (StreamOut[x].Data.Buffer, StreamIn[x2].Data.outframes);
10444 case StreamOut[x].Data.SampleFormat of
10445 0: StreamOut[x].Data.OutFrames :=
10446 sf_write_float (StreamOut[x].Data.HandleSt,
10447 @BufferCv[0], StreamIn[x2].Data.outframes * 2);
10448 1: StreamOut[x].Data.OutFrames :=
10449 sf_write_int (StreamOut[x].Data.HandleSt,
10450 @BufferCv[0], StreamIn[x2].Data.outframes * 2);
10451 2: StreamOut[x].Data.OutFrames :=
10452 sf_write_short (StreamOut[x].Data.HandleSt,
10453 @BufferCv[0], StreamIn[x2].Data.outframes * 2);
10454 end;
10455 end
10456 else
10457 begin
10458 case StreamOut[x].Data.SampleFormat of
10459 0: StreamOut[x].Data.OutFrames :=
10460 sf_write_float (StreamOut[x].Data.HandleSt,
10461 @StreamOut[x].Data.Buffer[0],
10462 StreamOut[x].Data.Wantframes * StreamOut[x].Data.channels);
10463 1: StreamOut[x].Data.OutFrames :=
10464 sf_write_int (StreamOut[x].Data.HandleSt,
10465 @StreamOut[x].Data.Buffer[0],
10466 StreamOut[x].Data.Wantframes * StreamOut[x].Data.channels);
10467 2: StreamOut[x].Data.OutFrames :=
10468 sf_write_short (StreamOut[x].Data.HandleSt,
10469 @StreamOut[x].Data.Buffer[0],
10470 StreamOut[x].Data.Wantframes * StreamOut[x].Data.channels);
10471 end;
10472 sf_write_sync (StreamOut[x].Data.HandleSt);
10473 // writeln (inttostr (StreamOut[x].Data.OutFrames));
10474 end;
10475 end;
10476
10477 {$endif}
10478
10479 0: // Give to wav file from TFileStream
10480 begin
10481 case StreamOut[x].Data.SampleFormat of
10482 0: rat := 2;
10483 1: rat := 2;
10484 2: rat := 1;
10485 end;
10486
10487 if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
10488 begin
10489
10490 BufferCv := CvStereoToMono (StreamOut[x].Data.Buffer, StreamIn[x2].Data.outframes);
10491 StreamOut[x].FileBuffer.Data.WriteBuffer (
10492 BufferCv[0],StreamIn[x2].Data.outframes * rat);
10493 end
10494 else
10495 if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 1) then
10496 begin
10497 StreamOut[x].FileBuffer.Data.WriteBuffer (
10498 StreamOut[x].Data.Buffer[0],
10499 StreamIn[x2].Data.outframes * StreamIn[x2].Data.ratio * rat);
10500 end
10501 else
10502 if (StreamOut[x].FileBuffer.wChannels = 2) and (StreamIn[x2].Data.Channels = 1) then
10503 begin
10504 BufferCv := CvMonoToStereo (StreamOut[x].Data.Buffer, StreamIn[x2].Data.outframes);
10505 StreamOut[x].FileBuffer.Data.WriteBuffer (
10506 BufferCv[0], StreamIn[x2].Data.outframes * 4);
10507 end
10508 else
10509 StreamOut[x].FileBuffer.Data.WriteBuffer (
10510 StreamOut[x].Data.Buffer[0],
10511 StreamIn[x2].Data.outframes * StreamIn[x2].Data.Channels * rat);
10512 end;
10513
10514 end;
10515end;
10516
10517
10518procedure Tuos_Player.WriteOutPlug (x:integer; x2 : integer);
10519var
10520 x3, x4, err, wantframestemp: integer;
10521 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10522 st : string;
10523 i : integer;
10524 {$endif}
10525 BufferplugINFLTMP: TDArFloat;
10526 BufferplugFL: TDArFloat;
10527 BufferplugSH: TDArShort;
10528 BufferplugLO: TDArLong;
10529 Bufferst2mo: TDArFloat;
10530begin
10531 // convert buffer if needed
10532 case StreamOut[x].Data.SampleFormat of
10533 1: StreamOut[x].Data.Buffer :=
10534 CvInt32toFloat32 (StreamOut[x].Data.Buffer);
10535 2: StreamOut[x].Data.Buffer :=
10536 CvInt16toFloat32 (StreamOut[x].Data.Buffer);
10537 end;
10538
10539 // transfer buffer out to temp
10540 SetLength (BufferplugINFLTMP, (StreamIn[x2].Data.outframes) * StreamIn[x2].Data.Channels);
10541
10542 if length (BufferplugINFLTMP) > 2 then
10543 for x3 := 0 to (length (BufferplugINFLTMP) div 2) - 1 do
10544 BufferplugINFLTMP[x3] := cfloat (StreamOut[x].Data.Buffer[x3]);
10545
10546 // dealing with input plugin
10547 for x3 := 0 to high (PlugIn) do
10548 begin
10549 if PlugIn[x3].Enabled = True then
10550 begin
10551 {$IF DEFINED (bs2b) or DEFINED (soundtouch) or DEFINED (noiseremoval)}
10552 BufferplugFL := Plugin[x3].PlugFunc (BufferplugINFLTMP,
10553 Plugin[x3].PlugHandle, Plugin[x3].Abs2b, StreamIn[x2].Data,
10554 Plugin[x3].param1, Plugin[x3].param2, Plugin[x3].param3, Plugin[x3].param4,
10555 Plugin[x3].param5, Plugin[x3].param6, Plugin[x3].param7, Plugin[x3].param8);
10556 {$endif}
10557
10558 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10559 writeln ('PlugFunc: Length (BufferplugINFLTMP,BufferplugFL) = ' +
10560 inttostr (Length (BufferplugINFLTMP)) + ' , ' + inttostr (Length (BufferplugFL))) ;
10561 {$endif}
10562
10563 if (length (PlugIn) > 1) then
10564 begin
10565 // TO CHECK : works only if SoundTouch is last or only plugin
10566 for x4 := 0 to length (BufferplugFL) - 1 do
10567 BufferplugINFLTMP[x4] := cfloat (BufferplugFL[x4]);
10568 end;
10569 end;
10570
10571 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10572 writeln ('2-PlugFunc: Length (BufferplugINFLTMP,BufferplugFL) = ' +
10573 inttostr (Length (BufferplugINFLTMP)) + ' , ' + inttostr (Length (BufferplugFL)));
10574 {$endif}
10575 end;
10576
10577 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10578 writeln ('Give the processed input to output.');
10579 writeln ('Length (BufferplugFL) = ' + inttostr (Length (BufferplugFL)));
10580 {$endif}
10581 if Length (BufferplugFL) > 0 then
10582 begin
10583
10584 case StreamOut[x].Data.SampleFormat of
10585 1:
10586 begin
10587 SetLength (BufferplugLO, length (BufferplugFL));
10588 BufferplugLO := CvFloat32ToInt32 (BufferplugFL);
10589 end;
10590 2:
10591 begin
10592 SetLength (BufferplugSH, length (BufferplugFL));
10593 BufferplugSH := CvFloat32ToInt16 (BufferplugFL);
10594
10595 end;
10596 end;
10597
10598 case StreamOut[x].Data.TypePut of
10599
10600 {$IF DEFINED (portaudio)}
10601 1: // Give to output device
10602 begin
10603
10604 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10605 writeln ('Before Pa_WriteStream: Length (BufferplugFL) = ' + inttostr (Length (
10606 BufferplugFL
10607 )));
10608 {$endif}
10609 case StreamOut[x].Data.SampleFormat of
10610 0:
10611 begin
10612 err :=
10613 Pa_WriteStream (StreamOut[x].Data.HandleSt,
10614 @BufferplugFL[0], Length (BufferplugFL) Div
10615 StreamIn[x2].Data.Channels);
10616 end;
10617 1:
10618 begin
10619 BufferplugLO := CvFloat32ToInt32 (BufferplugFL);
10620 err :=
10621 Pa_WriteStream (StreamOut[x].Data.HandleSt,
10622 @BufferplugLO[0], Length (BufferplugLO) Div
10623 StreamIn[x2].Data.Channels);
10624 end;
10625 2:
10626 begin
10627 BufferplugSH := CvFloat32ToInt16 (BufferplugFL);
10628
10629 err :=
10630 Pa_WriteStream (StreamOut[x].Data.HandleSt,
10631 @BufferplugSH[0], Length (BufferplugSH) Div
10632 StreamIn[x2].Data.Channels);
10633 end;
10634 end;
10635 // if err <> 0 then status := 0;// if you want clean buffer ...
10636
10637 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10638 writeln ('Pa_WriteStream error = '+ inttostr (err));
10639 {$endif}
10640 end;
10641 {$endif}
10642
10643 {$IF DEFINED (shout)}
10644 2: // Give to IceCast server
10645 begin
10646
10647{$IF DEFINED (uos_debug) and DEFINED (unix)}
10648 writeln ('Give to output IceCast server');
10649 {$endif}
10650
10651 case StreamOut[x].Data.SampleFormat of
10652 0:
10653 begin
10654 err := opus_encode_float (StreamOut[x].encoder, @BufferplugFL[0], cFRAME_SIZE,
10655 StreamOut[x].cbits, cMAX_PACKET_SIZE);
10656 end;
10657 1:
10658 begin
10659 err := opus_encode (StreamOut[x].encoder, @BufferplugLO[0], cFRAME_SIZE,
10660 StreamOut[x].cbits, cMAX_PACKET_SIZE);
10661 end;
10662 2:
10663 begin
10664 err := opus_encode (StreamOut[x].encoder, @BufferplugSH[0], cFRAME_SIZE,
10665 StreamOut[x].cbits, cMAX_PACKET_SIZE);
10666 end;
10667 end;
10668
10669 StreamOut[x].data.outframes := err;
10670
10671{$IF DEFINED (uos_debug) and DEFINED (unix)}
10672 WriteLn ('opus_encode outframes =' + inttostr (err));
10673 WriteLn ('----------------------------------');
10674 // writeln (tencoding.utf8.getstring (StreamOut[x].cbits));
10675 {$endif}
10676
10677 if err > 0 then
10678
10679 err := shout_send (StreamOut[x].Data.HandleSt, StreamOut[x].cbits, StreamOut[x].data.outframes);
10680
10681{$IF DEFINED (uos_debug) and DEFINED (unix)}
10682 if err = SHOUTERR_SUCCESS then
10683 WriteLn ('shout_send ok ' + inttostr (err))
10684 else
10685 WriteLn ('shout_send error: '+ inttostr (err) + ' ' + pchar (shout_get_error (
10686 StreamOut[x
10687 ].Data.HandleSt)));
10688 writeln ('End give output to IceCast server');
10689 {$endif}
10690
10691 shout_sync (StreamOut[x].Data.HandleSt);
10692 // ?
10693
10694 end;
10695 {$endif}
10696
10697 0:
10698 begin
10699 // Give to wav file from TFileStream
10700
10701 if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
10702 begin
10703 Bufferst2mo := CvStereoToMono (BufferplugFL, Length (BufferplugFL) Div 2);
10704 BufferplugSH := CvFloat32ToInt16 (Bufferst2mo);
10705 end
10706 else
10707 begin
10708 BufferplugSH := CvFloat32ToInt16 (BufferplugFL);
10709 end;
10710 StreamOut[x].FileBuffer.Data.WriteBuffer (BufferplugSH[0], Length (BufferplugSH));
10711
10712 end;
10713
10714 4:
10715 begin
10716 // Give to wav file from TMemoryStream
10717
10718 if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
10719 begin
10720 Bufferst2mo := CvStereoToMono (BufferplugFL, Length (BufferplugFL) Div 2);
10721 BufferplugSH := CvFloat32ToInt16 (Bufferst2mo);
10722 end
10723 else
10724 begin
10725 BufferplugSH := CvFloat32ToInt16 (BufferplugFL);
10726 end;
10727 StreamOut[x].FileBuffer.DataMS.WriteBuffer (BufferplugSH[0],
10728 Length (BufferplugSH));
10729
10730 end;
10731
10732 5: // Give to MemoryStream
10733 begin
10734
10735 case StreamOut[x].Data.SampleFormat of
10736 0: StreamOut[x].MemorySteamOut.WriteBuffer (BufferplugFL[0],
10737 Length (BufferplugFL));
10738
10739 1: StreamOut[x].MemorySteamOut.WriteBuffer (BufferplugLO[0],
10740 Length (BufferplugLO));
10741
10742 2: StreamOut[x].MemorySteamOut.WriteBuffer (BufferplugSH[0],
10743 Length (BufferplugSH));
10744
10745 end;
10746 end;
10747
10748
10749 3:
10750 begin
10751 // Give to memory buffer
10752 wantframestemp := Length (BufferplugFL);
10753 SetLength (Streamout[x].BufferOut^,length (Streamout[x].BufferOut^) + wantframestemp );
10754
10755 for x2 := 0 to wantframestemp -1 do
10756 Streamout[x].BufferOut^[Streamout[x].Data.posmem + x2] := BufferplugFL[x2];
10757
10758 Streamout[x].Data.posmem := Streamout[x].Data.posmem + wantframestemp;
10759
10760 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10761 writeln ('Streamout[x].Data.posmem = '+inttostr ( Streamout[x].Data.posmem));
10762 st := '';
10763 for i := 0 to length (tempoutmemory) -1 do
10764 st := st + '|' + inttostr (i) + '|' + floattostr (tempoutmemory[i]);
10765 WriteLn ('OUTPUT DATA AFTER4 ------------------------------');
10766 WriteLn (st);
10767 {$endif}
10768 end;
10769 end;
10770 end;
10771end;
10772
10773{$IF DEFINED (webstream)}
10774procedure Tuos_Player.ReadUrl(x: integer);
10775var
10776 err: integer;
10777 {$IF DEFINED(fdkaac)}
10778 FErrorCode: AAC_DECODER_ERROR;
10779 FByteFilled, FBytesRead: longword;
10780 FOutputBuff: array of cfloat;
10781 FCStreamInfo: PCStreamInfo;
10782 len, len2, len3: integer;
10783 rawAACBuffer: PByte;
10784 {$ENDIF}
10785 {$IF DEFINED(uos_debug) and DEFINED(unix)}
10786 i: integer;
10787 st: string;
10788 {$ENDIF}
10789begin
10790 case StreamIn[x].Data.LibOpen of
10791 1:
10792 begin
10793 {$IF DEFINED(mpg123)}
10794 {$IF DEFINED(uos_debug) and DEFINED(unix)}
10795 writeln('===> Before mpg123_read');
10796 {$ENDIF}
10797 err := mpg123_read(StreamIn[x].Data.HandleSt, @StreamIn[x].Data.Buffer[0],
10798 StreamIn[x].Data.wantframes, StreamIn[x].Data.outframes);
10799
10800 {$IF DEFINED(uos_debug) and DEFINED(unix)}
10801 writeln('===> mpg123_read error => ' + inttostr(err));
10802 {$ENDIF}
10803 StreamIn[x].Data.outframes := StreamIn[x].Data.outframes Div StreamIn[x].Data.Channels;
10804 {$ENDIF}
10805 end;
10806
10807 2:
10808 begin
10809 {$IF DEFINED(fdkaac)}
10810 setlength(FOutputBuff, StreamIn[x].Data.wantframes);
10811
10812 GetMem(rawAACBuffer, StreamIn[x].Data.wantframes);
10813
10814 FBytesRead := StreamIn[x].InPipe.Read(rawAACBuffer[0], 1024);
10815
10816 FByteFilled := FBytesRead;
10817 FErrorCode := aacDecoder_Fill(StreamIn[x].Data.HandleSt, @rawAACBuffer, FBytesRead, FByteFilled);
10818
10819 len2 := 0;
10820 len3 := 0;
10821
10822 while true do
10823 begin
10824 FErrorCode := aacDecoder_DecodeFrame(StreamIn[x].Data.HandleSt, PSmallInt(FOutputBuff),
10825 StreamIn[x].Data.wantframes, 0);
10826
10827 if (FErrorCode <> AAC_DECODER_ERROR.AAC_DEC_OK) then
10828 begin
10829 if FErrorCode = AAC_DECODER_ERROR.AAC_DEC_NOT_ENOUGH_BITS then
10830 break;
10831 end;
10832
10833 FCStreamInfo := aacDecoder_GetStreamInfo(StreamIn[x].Data.HandleSt);
10834 if ((not assigned(FCStreamInfo)) or (FCStreamInfo^.sampleRate <= 0)) then
10835 raise Exception.Create('No stream info');
10836
10837 for len := 0 to (FCStreamInfo^.frameSize) - 1 do
10838 begin
10839 StreamIn[x].Data.Buffer[len + len2] := FOutputBuff[len];
10840 inc(len3);
10841 end;
10842 len2 := len2 + FCStreamInfo^.frameSize;
10843 end;
10844
10845 StreamIn[x].Data.outframes := len3 * 2;
10846
10847 if StreamIn[x].Data.SampleFormat < 2 then
10848 begin
10849 StreamIn[x].Data.Buffer := CvInt16ToFloat32(StreamIn[x].Data.Buffer);
10850 if StreamIn[x].Data.SampleFormat = 1 then
10851 StreamIn[x].Data.Buffer := CvFloat32toInt32fl(StreamIn[x].Data.Buffer,
10852 length(StreamIn[x].Data.Buffer));
10853 end;
10854
10855 freemem(rawAACBuffer);
10856
10857 {$IF DEFINED(uos_debug) and DEFINED(unix)}
10858 writeln('FIN read url ok');
10859 {$ENDIF}
10860 {$ENDIF}
10861 end;
10862
10863 4:
10864 begin
10865 {$IF DEFINED(opus)}
10866 {$IF DEFINED(uos_debug) and DEFINED(unix)}
10867 writeln('===> Before op_read_x.');
10868 {$ENDIF}
10869
10870 case StreamIn[x].Data.SampleFormat of
10871 0:
10872 begin
10873 StreamIn[x].Data.outframes := cint(op_read_float(StreamIn[x].Data.HandleOP,
10874 @StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.Wantframes
10875 Div StreamIn[x].Data.channels), Nil));
10876 end;
10877 1:
10878 begin
10879 StreamIn[x].Data.outframes := cint(op_read_float(StreamIn[x].Data.HandleOP,
10880 @StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.Wantframes
10881 Div StreamIn[x].Data.channels), Nil));
10882
10883 // no int32 format with opus => need a conversion from float32 to int32.
10884 StreamIn[x].Data.Buffer := Cvfloat32ToInt32fl(StreamIn[x].Data.Buffer,
10885 StreamIn[x].Data.outframes * StreamIn[x].Data.Channels);
10886 end;
10887 2:
10888 begin
10889 StreamIn[x].Data.outframes := cint(op_read(StreamIn[x].Data.HandleOP,
10890 @StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.Wantframes
10891 Div StreamIn[x].Data.channels), Nil));
10892 end;
10893 end;
10894
10895 setlength(StreamIn[x].data.Buffer, StreamIn[x].Data.outframes * StreamIn[x].Data.Channels);
10896
10897 {$IF DEFINED(uos_debug) and DEFINED(unix)}
10898 writeln('Seek outframes = ' + inttostr(StreamIn[x].Data.outframes));
10899 st := '';
10900 for i := 0 to length(StreamIn[x].data.Buffer) - 1 do
10901 st := st + '|' + inttostr(i) + '|' + floattostr(StreamIn[x].data.Buffer[i]);
10902 WriteLn('OUTPUT DATA AFTER1 ------------------------------');
10903 // WriteLn(st);
10904 writeln(' StreamIn[x].Data.outframes = ' + inttostr(StreamIn[x].Data.outframes * StreamIn[x]
10905 .Data.Channels));
10906 {$ENDIF}
10907
10908 if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0;
10909 {$ENDIF}
10910 end;
10911 end;
10912
10913 if (StreamIn[x].Data.TypePut = 2) and ((StreamIn[x].Data.LibOpen = 1) or (StreamIn[x].Data
10914 .LibOpen = 4)) then
10915 begin
10916 if StreamIn[x].httpget.IsRunning = false then StreamIn[x].Data.status := 0;
10917 // no more data then close the stream
10918 {$IF DEFINED(uos_debug) and DEFINED(unix)}
10919 writeln('Check if internet is stopped.');
10920 {$ENDIF}
10921 end;
10922end;
10923{$endif}
10924
10925procedure Tuos_Player.ReadFile (x : integer);
10926{$IF DEFINED (neaac) or DEFINED (uos_debug)}
10927var
10928{$endif}
10929{$IF DEFINED (neaac)}
10930 outBytes: longword;
10931{$endif}
10932{$IF DEFINED (uos_debug) and DEFINED (unix)}
10933 i : integer;
10934 st : string;
10935{$endif}
10936begin
10937
10938 if length (StreamIn[x].Data.Buffer) <> StreamIn[x].Data.Wantframes then
10939 setlength (StreamIn[x].Data.Buffer,StreamIn[x].Data.Wantframes);
10940
10941 case StreamIn[x].Data.LibOpen of
10942 // Here we are, reading the data and store it in buffer
10943 {$IF DEFINED (sndfile)}
10944 0:
10945 begin
10946 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10947 WriteLn ('Before sf_read ' + inttostr (StreamIn[x].Data.Wantframes) +
10948 ' length (StreamIn[x].Data.Buffer ' +
10949 inttostr (length (StreamIn[x].Data.Buffer)));
10950 {$endif}
10951 case StreamIn[x].Data.SampleFormat of
10952 0: StreamIn[x].Data.OutFrames :=
10953 sf_read_float (StreamIn[x].Data.HandleSt,
10954 @StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes);
10955 1: StreamIn[x].Data.OutFrames :=
10956 sf_read_int (StreamIn[x].Data.HandleSt,
10957 @StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes);
10958 2: StreamIn[x].Data.OutFrames :=
10959 sf_read_short (StreamIn[x].Data.HandleSt,
10960 @StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes);
10961 end;
10962
10963 {$IF DEFINED (uos_debug) and DEFINED (unix)}
10964 writeln (inttostr (StreamIn[x].Data.lastbuf));
10965 WriteLn ('after sf_read');
10966 {$endif}
10967 if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0;
10968
10969 if (StreamIn[x].Data.lastbuf < 0) and (StreamIn[x].Data.outframes < StreamIn[x].Data.
10970 wantframes) then
10971 begin
10972 StreamIn[x].Data.outframes := StreamIn[x].Data.wantframes;
10973 StreamIn[x].Data.lastbuf := StreamIn[x].Data.lastbuf -1;
10974 if StreamIn[x].Data.lastbuf = -9 then StreamIn[x].Data.lastbuf := 0;
10975 end;
10976
10977 setlength (StreamIn[x].data.Buffer,StreamIn[x].Data.outframes);
10978
10979{$IF DEFINED (uos_debug) and DEFINED (unix)}
10980 st := '';
10981
10982 for i := 0 to length (StreamIn[x].data.Buffer) -1 do
10983 case StreamIn[x].Data.SampleFormat of
10984 0: st := st + '|' + inttostr (i) + '=' + floattostr (StreamIn[x].data.Buffer[i]);
10985 1: st := st + '|' + inttostr (i) + '=' + inttostr (cint32 (StreamIn[x].data.Buffer[i]));
10986 2: st := st + '|' + inttostr (i) + '=' + inttostr (cint16 (cint32 (StreamIn[x].data.Buffer[i])));
10987 end;
10988
10989 WriteLn ('OUTPUT DATA sf_read_ () ---------------------------');
10990 WriteLn ('StreamIn[x].Data.outframes = ' + inttostr (StreamIn[x].Data.outframes));
10991 WriteLn (st);
10992 {$endif}
10993
10994 end;
10995 {$endif}
10996 {$IF DEFINED (mpg123)}
10997 1:
10998 begin
10999
11000 mpg123_read (StreamIn[x].Data.HandleSt, @StreamIn[x].Data.Buffer[0],
11001 StreamIn[x].Data.wantframes, StreamIn[x].Data.outframes);
11002
11003 if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0;
11004
11005 setlength (StreamIn[x].data.Buffer,StreamIn[x].Data.outframes Div
11006 (StreamIn[x].Data.channels) );
11007
11008 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11009 st := '';
11010 for i := 0 to length (StreamIn[x].data.Buffer) -1 do
11011 case StreamIn[x].Data.SampleFormat of
11012 0: st := st + '|' + floattostr (StreamIn[x].data.Buffer[i]);
11013 1: st := st + '|' + inttostr (cint32 (StreamIn[x].data.Buffer[i]));
11014 2: st := st + '|' + inttostr (cint16 (cint32 (StreamIn[x].data.Buffer[i])));
11015 end;
11016 WriteLn ('OUTPUT DATA mpg123_read_ () ---------------------------');
11017 // WriteLn (st);
11018 {$endif}
11019
11020 StreamIn[x].Data.outframes :=
11021 StreamIn[x].Data.outframes Div StreamIn[x].Data.Channels;
11022 end;
11023 {$endif}
11024
11025 {$IF DEFINED (neaac)}
11026 2 :
11027 begin
11028 StreamIn[x].AACI.lwDataLen := 0;
11029 case StreamIn[x].AACI.outputFormat of
11030 FAAD_FMT_16BIT, FAAD_FMT_32BIT, FAAD_FMT_FLOAT :
11031 begin
11032 outBytes := StreamIn[x].Data.Wantframes;
11033 MP4GetData (StreamIn[x].AACI, StreamIn[x].AACI.pData, outBytes);
11034 Move (StreamIn[x].AACI.pData^, StreamIn[x].Data.Buffer[0],outBytes);
11035 StreamIn[x].AACI.lwDataLen := outBytes;
11036 end;
11037 end;
11038 if StreamIn[x].AACI.lwDataLen > (StreamIn[x].AACI.BitsPerSample div 8) then
11039 StreamIn[x].Data.outframes := trunc (StreamIn[x].AACI.lwDataLen / (StreamIn[x].AACI.BitsPerSample / 8))
11040 else
11041 StreamIn[x].Data.outframes := 0;
11042
11043 if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0;
11044
11045 // setlength (StreamIn[x].data.Buffer,StreamIn[x].Data.outframes * StreamIn[x].Data.channels );
11046
11047 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11048 st := '';
11049 for i := 0 to length (StreamIn[x].data.Buffer) -1 do
11050 case StreamIn[x].Data.SampleFormat of
11051 0: st := st + '|' + floattostr (StreamIn[x].data.Buffer[i]);
11052 1: st := st + '|' + inttostr (cint32 (StreamIn[x].data.Buffer[i]));
11053 2: st := st + '|' + inttostr (cint16 (cint32 (StreamIn[x].data.Buffer[i])));
11054 end;
11055 WriteLn ('OUTPUT DATA MP4GetData () ---------------------------');
11056 // WriteLn (st);
11057 {$endif}
11058
11059 end;
11060 {$endif}
11061
11062 {$IF DEFINED (cdrom)}
11063 3:
11064 begin
11065 StreamIn[x].pCD^.pDataLen := 0;
11066 case StreamIn[x].pCD^.BitsPerSample of
11067 16 :
11068 begin
11069 outBytes := StreamIn[x].Data.Wantframes;
11070 CDROM_GetData (StreamIn[x].pCD, StreamIn[x].pCD^.pData, outBytes);
11071 Move (StreamIn[x].pCD^.pData^, StreamIn[x].Data.Buffer[0], outBytes);
11072 StreamIn[x].pCD^.pDataLen := outBytes;
11073 end;
11074 end;
11075
11076 if StreamIn[x].pCD^.pDataLen > (StreamIn[x].pCD^.BitsPerSample div 8) then
11077 StreamIn[x].Data.outframes := StreamIn[x].pCD^.pDataLen Div (StreamIn[x].pCD^.BitsPerSample Div 8)
11078 else
11079 StreamIn[x].Data.outframes := 0;
11080
11081 end;
11082 {$endif}
11083
11084 {$IF DEFINED (opus)}
11085 4:
11086 begin
11087
11088 case StreamIn[x].Data.SampleFormat of
11089 0: StreamIn[x].Data.outframes := op_read_float (StreamIn[x].Data.HandleOP,
11090 @StreamIn[x].Data.Buffer[0],
11091 cint(StreamIn[x].Data.Wantframes Div StreamIn[x].Data.channels), Nil);
11092 1:
11093 begin
11094 StreamIn[x].Data.outframes := op_read_float (StreamIn[x].Data.HandleOP,
11095 @StreamIn[x].Data.Buffer[0],
11096 cint(StreamIn[x].Data.Wantframes Div StreamIn[x].Data.channels), Nil);
11097
11098 // no int32 format with opus => needs a conversion from float32 to int32.
11099 StreamIn[x].Data.Buffer := Cvfloat32ToInt32fl ( StreamIn[x].Data.Buffer,
11100 StreamIn[x].Data.outframes * StreamIn[x].Data.Channels );
11101 end;
11102 2:
11103 begin
11104 StreamIn[x].Data.outframes := op_read (StreamIn[x].Data.HandleOP,
11105 @StreamIn[x].Data.Buffer[0], cint (StreamIn[x].Data.Wantframes), Nil);
11106 end;
11107
11108 end;
11109
11110 setlength (StreamIn[x].data.Buffer,int32 (StreamIn[x].Data.outframes * StreamIn[x].Data.Channels));
11111
11112 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11113 st := '';
11114 for i := 0 to length (StreamIn[x].data.Buffer) -1 do
11115 case StreamIn[x].Data.SampleFormat of
11116 0: st := st + '|' + floattostr (StreamIn[x].data.Buffer[i]);
11117 1: st := st + '|' + inttostr (cint32 (StreamIn[x].data.Buffer[i]));
11118 2: st := st + '|' + inttostr (cint16 (cint32 (StreamIn[x].data.Buffer[i])));
11119 end;
11120 WriteLn ('OUTPUT DATA op_read_ ---------------------------');
11121 // WriteLn (st);
11122 {$endif}
11123
11124 if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0;
11125 StreamIn[x].Data.outframes := StreamIn[x].Data.outframes * StreamIn[x].Data.Channels;
11126
11127 end;
11128 {$endif}
11129
11130 {$IF DEFINED (xmp)}
11131 5:
11132 begin
11133 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11134 WriteLn ('Before xmp_play_buffer ' + inttostr (StreamIn[x].Data.Wantframes) +
11135 ' length (StreamIn[x].Data.Buffer ' +
11136 inttostr (length (StreamIn[x].Data.Buffer)));
11137 {$endif}
11138
11139 if xmp_play_buffer (StreamIn[x].Data.HandleSt,
11140 @StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes * StreamIn[x].Data.channels , 1) < 0 then
11141 StreamIn[x].Data.outframes := 0
11142 else
11143 begin
11144 StreamIn[x].Data.outframes := StreamIn[x].Data.Wantframes;
11145
11146 if StreamIn[x].Data.SampleFormat < 2 then
11147 begin
11148 StreamIn[x].Data.Buffer := CvInt16ToFloat32 (StreamIn[x].Data.Buffer);
11149 if StreamIn[x].Data.SampleFormat = 1 then
11150 StreamIn[x].Data.Buffer := CvFloat32toInt32fl (StreamIn[x].Data.Buffer, length(StreamIn[x].Data.Buffer));
11151 end;
11152 end;
11153
11154 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11155 writeln (inttostr (StreamIn[x].Data.lastbuf));
11156 WriteLn ('after xmp_play_buffer');
11157 {$endif}
11158 setlength (StreamIn[x].data.Buffer,StreamIn[x].Data.outframes);
11159
11160 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11161
11162 st := '';
11163
11164 for i := 0 to length (StreamIn[x].data.Buffer) -1 do
11165 begin
11166 st := st + '|' + inttostr (i) + '=' + inttostr(cint16 (cint32 (StreamIn[x].data.Buffer[i])));
11167 end;
11168
11169 WriteLn ('OUTPUT DATA xmp_read_ ---------------------------');
11170 WriteLn ('StreamIn[x].Data.outframes = ' + inttostr(StreamIn[x].Data.outframes));
11171 // WriteLn (st);
11172 {$endif}
11173
11174 end;
11175 {$endif}
11176
11177 99: // if nothing was defined
11178 end;
11179
11180 SetLength (StreamIn[x].Data.Buffer, StreamIn[x].Data.outframes);
11181end;
11182
11183procedure Tuos_Player.CheckIfPaused;
11184begin
11185 if isGlobalPause = true then
11186 begin
11187 RTLeventWaitFor (uosInit.evGlobalPause);
11188 RTLeventSetEvent (uosInit.evGlobalPause);
11189 end
11190 else
11191 begin
11192 RTLeventWaitFor (evPause);
11193 // is there a pause waiting ?
11194 RTLeventSetEvent (evPause);
11195 end;
11196end;
11197
11198{$IF DEFINED (mse)}
11199function Tuos_Player.execute (thread: tmsethread): integer;
11200// The Main Loop Procedure
11201{$else}
11202procedure TuosThread.Execute;
11203// The Main Loop Procedure
11204{$endif}
11205var
11206 x, x2, x3 : cint32;
11207 plugenabled: boolean;
11208 curpos: cint64 = 0;
11209 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11210 st : string;
11211 i : integer;
11212 {$endif}
11213
11214begin
11215
11216 theinc := 0;
11217
11218 {$IF DEFINED (mse)}
11219 {$else}
11220 with Tuos_Player (theparent) do
11221 begin
11222 {$endif}
11223
11224 CheckIfPaused;
11225 // is there a pause waiting ?
11226
11227 DoBeginMethods ();
11228
11229 CheckIfPaused;
11230 // is there a pause waiting ?
11231
11232 repeat
11233
11234 if uosIsActif then DoLoopBeginMethods
11235 else nofree := false;
11236
11237 CheckIfPaused;
11238 // is there a pause waiting ?
11239 // Dealing with input
11240 for x := 0 to high (StreamIn) do
11241 begin
11242
11243 if (StreamIn[x].data.hasfilters) and uosIsActif then
11244 begin
11245 setlength (StreamIn[x].Data.levelfiltersar,StreamIn[x].Data.nbfilters * StreamIn[x].Data.channels );
11246 StreamIn[x].Data.incfilters := 0;
11247 end;
11248
11249 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11250 WriteLn ('Before for x := 0 to high (StreamIn)');
11251 {$endif}
11252
11253 CheckIfPaused;
11254 // is there a pause waiting ?
11255
11256 if (StreamIn[x].Data.Status > 0) and
11257 (StreamIn[x].Data.Enabled = True) then
11258 begin
11259
11260 StreamIn[x].Data.levelfilters := '';
11261
11262 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11263 WriteLn ('Before StreamIn[x].Data.Seekable = True');
11264 {$endif}
11265 if (StreamIn[x].Data.Poseek > -1) and (StreamIn[x].Data.Seekable = True) and (uosIsActif)
11266 then
11267 begin
11268 // there is a seek waiting
11269
11270 DoSeek (x);
11271
11272 curpos := StreamIn[x].Data.Poseek;
11273 StreamIn[x].Data.Poseek := -1;
11274 end;
11275
11276 if (StreamIn[x].Data.positionEnable = 1) and (StreamIn[x].Data.Seekable = True)
11277 then
11278 StreamIn[x].Data.position := curpos;
11279
11280 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11281 writeln ('DSPin BeforeBufProc 1');
11282 {$endif}
11283 if (StreamIn[x].Data.Status = 1) and (length (StreamIn[x].DSP) > 0) then
11284 DoDSPinBeforeBufProc (x);
11285 // Procedure in DSP to execute before fill buffer.
11286 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11287 writeln ('DSPin BeforeBufProc 2');
11288 {$endif}
11289
11290 if uosIsActif then
11291 begin
11292 CheckIfPaused;
11293 // is there a pause waiting ?
11294 case StreamIn[x].Data.TypePut of
11295
11296 0: // It is an input from audio file.
11297 ReadFile (x);
11298
11299 {$IF DEFINED (portaudio)}
11300 1: // for Input from device
11301 ReadDevice (x);
11302 {$endif}
11303
11304 {$IF DEFINED (webstream)}
11305 2: // for Input from Internet audio stream.
11306 ReadUrl (x);
11307 {$ENDIF}
11308
11309 {$IF DEFINED (synthesizer)}
11310 3: // for Input from Synthesizer
11311 ReadSynth (x);
11312 {$endif}
11313
11314 4: // for Input from memory
11315 ReadMem (x);
11316
11317 5: // for Input from endless muted
11318 ReadEndless (x);
11319
11320 6: // for Input from decoded memory-stream
11321 ReadMemDec (x);
11322
11323 end;
11324 //case StreamIn[x].Data.TypePut of
11325
11326 end
11327 else StreamIn[x].Data.OutFrames := 0;
11328
11329 if StreamIn[x].Data.OutFrames = 0 then StreamIn[x].Data.status := 0;
11330
11331 if (StreamIn[x].Data.Seekable = True) then if StreamIn[x].Data.OutFrames < 100 then
11332 StreamIn[x].Data.status := 0;
11333 // no more data then close the stream
11334
11335 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11336 writeln ('StreamIn[x].Data.status = ' + inttostr (StreamIn[x].Data.status));
11337 {$endif}
11338
11339 if StreamIn[x].Data.status > 0 then // still working
11340 begin
11341
11342 if (StreamIn[x].Data.positionEnable = 1) then
11343 begin
11344 if (StreamIn[x].Data.LibOpen = 1) and (StreamIn[x].Data.SampleFormat < 2)
11345 then
11346 curpos := curpos + (StreamIn[x].Data.OutFrames Div
11347 (StreamIn[x].Data.Channels * 2))
11348 // strange outframes float 32 with Mpg123 ?
11349 else
11350 curpos := curpos + (StreamIn[x].Data.OutFrames Div
11351 (StreamIn[x].Data.Channels));
11352
11353 StreamIn[x].Data.position := curpos;
11354 // new position
11355 end;
11356
11357 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11358 writeln ('Getting the level before DSP procedure');
11359 {$endif}
11360
11361 if (StreamIn[x].Data.levelEnable = 1) or (StreamIn[x].Data.levelEnable = 3) then
11362 StreamIn[x].Data := DSPLevel(StreamIn[x].Data);
11363
11364 // Adding level in array-level// ideal for pre-wave form
11365 if (StreamIn[x].Data.levelArrayEnable = 1) then
11366 begin
11367 if (StreamIn[x].Data.levelEnable = 0) or (StreamIn[x].Data.levelEnable = 3)
11368 then
11369 StreamIn[x].Data := DSPLevel (StreamIn[x].Data);
11370 DoArrayLevel (x);
11371 end;
11372
11373 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11374 writeln ('DSPin AfterBuffProcBefore');
11375 {$endif}
11376
11377 if (StreamIn[x].Data.Status = 1) and (length (StreamIn[x].DSP) > 0) then
11378 DoDSPinAfterBufProc (x);
11379 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11380 writeln ('DSPin AfterBuffProcAfter');
11381 {$endif}
11382
11383 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11384 writeln ('The synchro main loop procedurebefore');
11385 {$endif}
11386 DoMainLoopProc (x);
11387
11388 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11389 writeln ('Getting the level after DSP procedure');
11390 {$endif}
11391
11392 // Getting the level after DSP procedure
11393 if ( (StreamIn[x].Data.levelEnable = 2) or (StreamIn[x].Data.levelEnable = 3))
11394 then StreamIn[x].Data := DSPLevel (StreamIn[x].Data);
11395
11396 // Adding level in array-level
11397 if (StreamIn[x].Data.levelArrayEnable = 2) then
11398 begin
11399 if (StreamIn[x].Data.levelEnable = 0) or (StreamIn[x].Data.levelEnable = 1)
11400 then
11401 StreamIn[x].Data := DSPLevel (StreamIn[x].Data);
11402 DoArrayLevel (x);
11403 end;
11404
11405 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11406 writeln ('End level after DSP procedure');
11407 {$endif}
11408
11409 end;
11410 end;
11411 end;
11412 // end for low (StreamIn[x]) to high (StreamIn[x])
11413
11414 // Seeking if StreamIn is terminated
11415 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11416 writeln ('Seeking if StreamIn is terminated');
11417 {$endif}
11418
11419 if status <> 0 then SeekIfTerminated;
11420
11421 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11422 writeln ('status = ' +inttostr (status));
11423 {$endif}
11424
11425 CheckIfPaused;
11426 // is there a pause waiting ?
11427
11428 // Give Buffer to Output
11429 if status = 1 then
11430 begin
11431 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11432 writeln ('Give Buffer to Output');
11433 {$endif}
11434
11435 if uosIsActif then for x := 0 to high (StreamOut) do
11436
11437 if (StreamOut[x].Data.Enabled = True) then
11438 begin
11439
11440 if StreamOut[x].data.hasfilters then
11441 begin
11442 setlength (StreamOut[x].Data.levelfiltersar,
11443 StreamOut[x].Data.nbfilters * StreamOut[x].Data.channels);
11444 StreamOut[x].Data.incfilters := 0;
11445 end;
11446
11447 for x2 := 0 to high (StreamOut[x].Data.Buffer) do
11448 StreamOut[x].Data.Buffer[x2] := cfloat (0.0);
11449 // clear output
11450 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11451 writeln ('Buffer[x2] := cfloat (0.0)');
11452 {$endif}
11453 for x2 := 0 to high (StreamIn) do
11454 if (StreamIn[x2].Data.status > 0) and
11455 (StreamIn[x2].Data.Enabled = True) and
11456 ((StreamIn[x2].Data.Output = x) or (StreamIn[x2].Data.Output = -1))
11457 then
11458 begin
11459 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11460 writeln ('length (StreamIn[x2].Data.Buffer) = ' +inttostr
11461 (
11462 length (StreamIn[x2].Data.Buffer)));
11463 writeln ('length (StreamOut[x].Data.Buffer) = ' +inttostr
11464 (
11465 length (StreamOut[x].Data.Buffer)));
11466 writeln ('for x3 := 0 to high (StreamIn[x2].Data.Buffer) do');
11467 writeln ('high (StreamIn[x2].Data.Buffer) = '+ inttostr (
11468 high (StreamIn[x2].Data.Buffer)));
11469 {$endif}
11470
11471 for x3 := 0 to high (StreamIn[x2].Data.Buffer) do
11472 begin
11473 if x3 < high (StreamOut[x].Data.Buffer) + 1 then
11474 StreamOut[x].Data.Buffer[x3] := cfloat (StreamOut[x].Data.Buffer[x3])
11475 + cfloat (StreamIn[x2].Data.Buffer[x3]);
11476 end;
11477
11478 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11479 WriteLn ('StreamOut[x].Data.Buffer -------');
11480 st := '';
11481 for i := 0 to length (StreamOut[0].Data.Buffer) -1 do
11482 st := st + '|' + inttostr (i) + '=' +
11483 floattostr (Streamout[0].Data.Buffer[i]);
11484 // WriteLn (st);
11485 writeln ('for x3 := 0 to high (StreamIn[x2].Data.Buffer) done');
11486 {$endif}
11487
11488 case StreamIn[x2].Data.LibOpen of
11489 0: StreamOut[x].Data.outframes := StreamIn[x2].Data.outframes;
11490 // sndfile
11491 1: StreamOut[x].Data.outframes := StreamIn[x2].Data.outframes Div
11492 StreamIn[x2].Data.Channels;
11493 // mpg123
11494 2: StreamOut[x].Data.outframes := StreamIn[x2].Data.outframes;
11495 // aac
11496 3: StreamOut[x].Data.outframes := StreamIn[x2].Data.outframes;
11497 // CDRom
11498 4: StreamOut[x].Data.outframes := StreamIn[x2].Data.outframes;
11499 // opus
11500 end;
11501 end;
11502
11503 // copy buffer-in into buffer-out
11504 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11505 writeln ('copy buffer-in into buffer-out');
11506 {$endif}
11507
11508 // calcul level before all dsp
11509 if (Streamout[x].Data.levelEnable = 1) then
11510 Streamout[x].Data := DSPLevelOut(Streamout[x].Data);
11511
11512 // DSPOut AfterBuffProc
11513 if (length (StreamOut[x].DSP) > 0) and uosIsActif then
11514 DoDSPOutAfterBufProc (x);
11515
11516 // apply plugin (ex: SoundTouch Library)
11517 plugenabled := False;
11518
11519 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11520 writeln (' if (length (Plugin) > 0) then');
11521 {$endif}
11522
11523 if (length (Plugin) > 0) then
11524 begin
11525 for x3 := 0 to high (PlugIn) do
11526 if Plugin[x3].Enabled = True then
11527 plugenabled := True;
11528 end;
11529
11530 // calcul level after all dsp
11531 if (Streamout[x].Data.levelEnable = 2) then
11532 Streamout[x].Data := DSPLevelOut(Streamout[x].Data);
11533
11534 if uosIsActif then
11535 begin
11536 if plugenabled = True then
11537 WriteOutPlug (x, x2)
11538 else// No plugin
11539 WriteOut (x, x2);
11540 end;
11541 end;
11542 end;
11543
11544 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11545 WriteLn ('Before LoopEndProc ------------------------------');
11546 {$endif}
11547
11548 if uosIsActif then DoLoopEndMethods;
11549
11550 if length (StreamIn) > 1 then // clear buffer for multi-input
11551 for x2 := 0 to high (StreamIn) do
11552 for x3 := 0 to high (StreamIn[x2].Data.Buffer) do
11553 StreamIn[x2].Data.Buffer[x3] := cfloat (0.0);
11554
11555 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11556 WriteLn ('Before if (nofree = true) and (status = 0)-----');
11557 {$endif}
11558
11559 if (nofree = true) and (status = 0) then
11560
11561 DoTerminateNoFreePlayer;
11562
11563 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11564 WriteLn ('Before until status = 0;----');
11565 {$endif}
11566
11567 until status = 0;
11568
11569 // End of Loop ---
11570
11571 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11572 WriteLn ('Before Terminate Thread---');
11573 {$endif}
11574
11575 // Terminate Thread
11576 if status = 0 then
11577 begin
11578
11579 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11580 writeln ('Status = 0');
11581 {$endif}
11582
11583 DoTerminatePlayer;
11584
11585 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11586 writeln ('EndProc---');
11587 {$endif}
11588
11589 if uosIsActif then DoEndProc;
11590
11591 if uosIsActif then if EndProcOnly <> nil then EndProcOnly;
11592
11593 isAssigned := false;
11594
11595 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11596 writeln ('EndProc All');
11597 {$endif}
11598 end;
11599
11600 {$IF DEFINED (uos_debug) and DEFINED (unix)}
11601 writeln ('This is the end...');
11602 {$endif}
11603
11604 {$IF DEFINED (mse)}
11605
11606 {$else}
11607 // FreeOnTerminate:=True;
11608 // terminate ();
11609 end;
11610 {$endif}
11611end;
11612
11613procedure Tuos_Init.unloadPlugin (PluginName: Pchar);
11614// Unload Plugin...
11615begin
11616 {$IF DEFINED (soundtouch)}
11617 if lowercase (PluginName) = 'soundtouch' then st_Unload ();
11618 {$endif}
11619 {$IF DEFINED (bs2b)}
11620 if lowercase (PluginName) = 'bs2b' then bs_Unload ();
11621 {$endif}
11622end;
11623
11624procedure Tuos_Init.unloadlib;
11625begin
11626 {$IF DEFINED (sndfile)}
11627 Sf_Unload ();
11628 {$endif}
11629 {$IF DEFINED (mpg123)}
11630 Mp_Unload ();
11631 {$endif}
11632 {$IF DEFINED (xmp)}
11633 xmp_Unload ();
11634 {$endif}
11635 {$IF DEFINED (portaudio)}
11636 Pa_Unload ();
11637 {$endif}
11638 {$IF DEFINED (neaac)}
11639 Aa_Unload;
11640 {$endif}
11641 {$IF DEFINED (fdkaac)}
11642 ad_Unload;
11643 {$endif}
11644 {$IF DEFINED (opus)}
11645 of_Unload;
11646 {$endif}
11647 {$IF DEFINED (windows)}
11648 Set8087CW (old8087cw);
11649 {$endif}
11650end;
11651
11652function Tuos_Init.InitLib (): cint32;
11653begin
11654 Result := -1;
11655 {$IF DEFINED (mpg123)}
11656 if (uosLoadResult.MPloadERROR = 0) then
11657 if mpg123_init () = MPG123_OK then
11658 begin
11659 mpversion := UTF8Decode (mpg123_decoders ()^);
11660 uosLoadResult.MPinitError := 0;
11661 Result := 0;
11662 end
11663 else
11664 begin
11665 Result := -2;
11666 uosLoadResult.MPinitError := 1;
11667 end;
11668 {$endif}
11669
11670 {$IF DEFINED (portaudio)}
11671 if (uosLoadResult.PAloadERROR = 0) then
11672 begin
11673 uosLoadResult.PAinitError := Pa_Initialize ();
11674 paversion := UTF8Decode (Pa_GetVersionText ());
11675 if uosLoadResult.PAinitError = 0 then
11676 begin
11677 Result := 0;
11678 DefDevInInfo := Nil;
11679 DefDevOutInfo := Nil;
11680
11681 DefDevOut := Pa_GetDefaultOutputDevice ();
11682 if DefDevOut >= 0 then
11683 DefDevOutInfo := Pa_GetDeviceInfo (DefDevOut);
11684 if DefDevOutInfo <> nil then
11685 DefDevOutAPIInfo := Pa_GetHostApiInfo (DefDevOutInfo^.hostApi);
11686
11687 DefDevIn := Pa_GetDefaultInputDevice ();
11688 if DefDevIn >= 0 then
11689 DefDevInInfo := Pa_GetDeviceInfo (DefDevIn);
11690 if DefDevInInfo <> nil then
11691 DefDevInAPIInfo := Pa_GetHostApiInfo (DefDevInInfo^.hostApi);
11692 end;
11693 end;
11694 {$endif}
11695
11696 {$IF DEFINED (sndfile)}
11697 if (Result = -1) and (uosLoadResult.SFloadERROR = 0) then
11698 begin
11699 sfversion := UTF8Decode (sf_version_string ());
11700 Result := 0;
11701 end;
11702 {$endif}
11703
11704 {$IF DEFINED (xmp)}
11705 if (Result = -1) and (uosLoadResult.XMloadERROR = 0) then
11706 begin
11707 Result := 0;
11708 end;
11709 {$endif}
11710end;
11711
11712function Tuos_Init.loadlib (): cint32;
11713begin
11714 Result := -1;
11715 uosLoadResult.PAloadERROR := -1;
11716 uosLoadResult.SFloadERROR := -1;
11717 uosLoadResult.MPloadERROR := -1;
11718 uosLoadResult.AAloadError := -1;
11719 uosLoadResult.OPloadERROR := -1;
11720 uosLoadResult.STloadERROR := -1;
11721 uosLoadResult.BSloadERROR := -1;
11722 uosLoadResult.XMloadERROR := -1;
11723 uosLoadResult.FAloadERROR := -1;
11724
11725 {$IF DEFINED (portaudio)}
11726 if (PA_FileName <> nil) and (PA_FileName <> '') then
11727 begin
11728 if PA_FileName = 'system' then PA_FileName := '';
11729 if Pa_Load (PA_FileName) then
11730 begin
11731 Result := 0;
11732 uosLoadResult.PAloadERROR := 0;
11733 uosDefaultDeviceOut := Pa_GetDefaultOutPutDevice();
11734 uosDefaultDeviceIn := Pa_GetDefaultInPutDevice();
11735 uosDeviceCount := Pa_GetDeviceCount();
11736 end
11737 else
11738 uosLoadResult.PAloadERROR := 2;
11739 end
11740 else
11741 uosLoadResult.PAloadERROR := -1;
11742 {$endif}
11743
11744 {$IF DEFINED (sndfile)}
11745 if (SF_FileName <> nil) and (SF_FileName <> '') then
11746 begin
11747 if Sf_FileName = 'system' then sf_FileName := '';
11748 if Sf_Load (SF_FileName) then
11749 begin
11750 uosLoadResult.SFloadERROR := 0;
11751 if uosLoadResult.PAloadERROR = -1 then
11752 Result := 0;
11753 end
11754 else
11755 begin
11756 uosLoadResult.SFloadERROR := 2;
11757 Result := -1;
11758 end;
11759 end
11760 else
11761 uosLoadResult.SFloadERROR := -1;
11762 {$endif}
11763
11764 {$IF DEFINED (mpg123)}
11765 if (MP_FileName <> nil) and (MP_FileName <> '') then
11766 begin
11767 if mp_FileName = 'system' then mp_FileName := '';
11768 if mp_Load (Mp_FileName) then
11769 begin
11770 uosLoadResult.MPloadERROR := 0;
11771 if (uosLoadResult.PAloadERROR = -1) and (uosLoadResult.SFloadERROR = -1) then
11772 Result := 0;
11773 end
11774 else
11775 begin
11776 uosLoadResult.MPloadERROR := 2;
11777 Result := -1;
11778 end;
11779 end
11780 else
11781 uosLoadResult.MPloadERROR := -1;
11782 {$endif}
11783
11784 {$IF DEFINED (neaac)}
11785 if (AA_FileName <> nil) and (AA_FileName <> '') and (M4_FileName <> nil) and (M4_FileName <> '')
11786 then
11787 begin
11788 if m4_FileName = 'system' then m4_FileName := '';
11789 if aa_FileName = 'system' then aa_FileName := '';
11790
11791 if aa_load (UTF8String (M4_FileName), UTF8String (AA_FileName)) then
11792 begin
11793 uosLoadResult.AAloadERROR := 0;
11794 if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
11795 (uosLoadResult.SFloadERROR = -1) then
11796 Result := 0;
11797 end
11798 else
11799 begin
11800 uosLoadResult.AAloadERROR := 2;
11801 Result := -1;
11802 end;
11803 end
11804 else
11805 uosLoadResult.AAloadERROR := -1;
11806 {$endif}
11807
11808 {$IF DEFINED (opus)}
11809 if (OF_FileName <> nil) and (OF_FileName <> '') then
11810 begin
11811 if of_FileName = 'system' then of_FileName := '';
11812 if (of_load (UTF8String (OF_FileName))) then
11813 begin
11814 uosLoadResult.OPloadERROR := 0;
11815 if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
11816 (uosLoadResult.SFloadERROR = -1) and (uosLoadResult.AAloadERROR = -1)
11817 then
11818 Result := 0;
11819 end
11820 else
11821 begin
11822 uosLoadResult.OPloadERROR := 2;
11823 Result := -1;
11824 end;
11825 end
11826 else
11827 uosLoadResult.OPloadERROR := -1;
11828 {$endif}
11829
11830 {$IF DEFINED (xmp)}
11831 if (XM_FileName <> nil) and (XM_FileName <> '') then
11832 begin
11833 if XM_FileName = 'system' then XM_FileName := '';
11834 if (xmp_Load (UTF8String (XM_FileName))) then
11835 begin
11836 uosLoadResult.XMloadERROR := 0;
11837 if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
11838 (uosLoadResult.SFloadERROR = -1) and (uosLoadResult.AAloadERROR = -1) and
11839 (uosLoadResult.OPloadERROR = -1)
11840 then
11841 Result := 0;
11842 end
11843 else
11844 begin
11845 uosLoadResult.XMloadERROR := 2;
11846 Result := -1;
11847 end;
11848 end
11849 else
11850 uosLoadResult.XMloadERROR := -1;
11851 {$endif}
11852
11853 {$IF DEFINED (fdkaac)}
11854 if (FA_FileName <> nil) and (FA_FileName <> '') then
11855 begin
11856 if FA_FileName = 'system' then FA_FileName := '';
11857 if (ad_Load (UTF8String (FA_FileName))) then
11858 begin
11859 uosLoadResult.FAloadERROR := 0;
11860 if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
11861 (uosLoadResult.SFloadERROR = -1) and (uosLoadResult.AAloadERROR = -1) and
11862 (uosLoadResult.OPloadERROR = -1) and (uosLoadResult.XMloadERROR = -1)
11863 then
11864 Result := 0;
11865 end
11866 else
11867 begin
11868 uosLoadResult.FAloadERROR := 2;
11869 Result := -1;
11870 end;
11871 end
11872 else
11873 uosLoadResult.FAloadERROR := -1;
11874 {$endif}
11875
11876 if Result = 0 then Result := InitLib ();
11877end;
11878
11879function uos_loadPlugin (PluginName, PluginFilename: PChar) : cint32;
11880begin
11881 Result := -1;
11882 {$IF DEFINED (soundtouch)}
11883 if ( (lowercase (PluginName) = 'soundtouch') or (lowercase (PluginName) = 'getbpm')) and (
11884 PluginFileName <> nil) and (PluginFileName <> '') then
11885 begin
11886 if PluginFileName = 'system' then PluginFileName := '';
11887 if ST_Load (PluginFileName) then
11888 begin
11889 Result := 0;
11890 uosLoadResult.STloadERROR := 0;
11891 uosInit.Plug_ST_FileName := PluginFileName;
11892 end
11893 else
11894 begin
11895 uosLoadResult.STloadERROR := 2;
11896 Result := -1;
11897 end;
11898 end;
11899 {$endif}
11900
11901 {$IF DEFINED (bs2b)}
11902 if (lowercase (PluginName) = 'bs2b') and (PluginFileName <> nil) and (PluginFileName <> '') then
11903 begin
11904 if PluginFileName = 'system' then PluginFileName := '';
11905 if BS_Load (PluginFileName) then
11906 begin
11907 Result := 0;
11908 uosLoadResult.BSloadERROR := 0;
11909 uosInit.Plug_BS_FileName := PluginFileName;
11910 end
11911 else
11912 begin
11913 uosLoadResult.BSloadERROR := 2;
11914 Result := -1;
11915 end;
11916 end;
11917 {$endif}
11918end;
11919
11920{$IF DEFINED (shout)}
11921function uos_LoadServerLib (ShoutFileName, OpusFileName : PChar) : cint32;
11922// Shout => needed for dealing with IceCast server
11923// Opus => needed for dealing with encoding opus stream
11924begin
11925 Result := -1;
11926 if not fileexists (ShoutFileName) then
11927 else
11928 if sh_Load (UTF8String (ShoutFileName)) then
11929 Result := 0;
11930
11931 if result = 0 then
11932 if not fileexists (OpusFileName) then
11933 Result := -2
11934 else
11935 if op_Load (UTF8String (OpusFileName)) then
11936 Result := 0
11937 else Result := -1;
11938end;
11939
11940procedure uos_unloadServerLib ();
11941// Unload server libraries... Do not forget to call it before close application...
11942begin
11943 shout_shutdown;
11944 sh_unload;
11945 op_unload;
11946end;
11947{$endif}
11948
11949function uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
11950 FaadFileName
11951 , opusfileFileName, XMPFileName, fdkaacFilename : PChar) : cint32;
11952begin
11953 result := -1;
11954 if not assigned (uosInit) then
11955 begin
11956
11957 {$IF DEFINED (windows)}
11958 old8087cw := Get8087CW;
11959 Set8087CW ($133f);
11960 {$endif}
11961
11962 uosInit := TUOS_Init.Create;
11963 // Create Libraries Loader-Init
11964 end;
11965
11966 uosInit.PA_FileName := PortAudioFileName;
11967 uosInit.SF_FileName := SndFileFileName;
11968 uosInit.MP_FileName := Mpg123FileName;
11969 uosInit.AA_FileName := FaadFileName;
11970 uosInit.M4_FileName := Mp4ffFileName;
11971 uosInit.OF_FileName := opusfileFileName;
11972 uosInit.XM_FileName := XMPFileName;
11973 uosInit.FA_FileName := fdkaacFilename;
11974
11975 result := uosInit.loadlib;
11976end;
11977
11978function uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
11979 FaadFileName, opusfileFileName, XMPFileName : PChar) : cint32;
11980begin
11981 result := uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
11982 FaadFileName, opusfileFileName, XMPFileName, Nil);
11983end;
11984
11985function uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
11986 FaadFileName, opusfileFileName: PChar) : cint32;
11987begin
11988 result := uos_loadlib (PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
11989 FaadFileName, opusfileFileName, Nil, Nil);
11990end;
11991
11992function uos_GetVersion () : cint32;
11993begin
11994 result := uos_version;
11995end;
11996
11997function Tuos_Player.SetGlobalEvent (isenabled : boolean) : boolean;
11998// Set the RTL Events Global (will pause/start/replay all the players synchro with same rtl event))
11999// result : true if set ok.
12000begin
12001 result := false;
12002 if (isAssigned = True) then
12003 begin
12004 isGlobalPause := isenabled;
12005 result := true;
12006 end;
12007end;
12008
12009procedure uos_unloadlib ();
12010begin
12011 if assigned (uosInit) then
12012 begin
12013 uosInit.unloadlib;
12014 end;
12015end;
12016
12017procedure uos_unloadlibCust (PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
12018// Custom Unload libraries... if true, then unload the library. You may unload what and when you want...
12019begin
12020 uosInit.unloadlibcust (PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac);
12021end;
12022
12023procedure uos_UnloadPlugin (PluginName: PChar);
12024// load plugin...
12025begin
12026 uosInit.unloadplugin (PluginName);
12027end;
12028
12029function uos_GetInfoLibraries () : PansiChar;
12030begin
12031 result := pchar (paversion + ' | Sndfile: ' + sfversion + ' | Mpg123: ' + mpversion);
12032end;
12033
12034{$IF DEFINED (portaudio)}
12035procedure uos_UpdateDevice ();
12036begin
12037 Pa_Terminate ();
12038 Pa_Initialize ();
12039end;
12040
12041procedure uos_GetInfoDevice ();
12042var
12043 x: cint32;
12044 devinf: PPaDeviceInfo;
12045 apiinf: PPaHostApiInfo;
12046begin
12047 x := 0;
12048 uosDeviceCount := 0;
12049 SetLength (uosDeviceInfos, 0);
12050
12051 uos_UpdateDevice ();
12052
12053 if Pa_GetDeviceCount () > 0 then
12054 begin
12055 uosDeviceCount := Pa_GetDeviceCount ();
12056
12057 SetLength (uosDeviceInfos, uosDeviceCount);
12058 uosDefaultDeviceOut := Pa_GetDefaultOutPutDevice ();
12059 uosDefaultDeviceIn := Pa_GetDefaultInPutDevice ();
12060
12061 while x < uosDeviceCount do
12062 begin
12063 uosDeviceInfos[x].DeviceNum := x;
12064
12065 devinf := Pa_GetDeviceInfo (x);
12066 apiinf := Pa_GetHostApiInfo (devinf^.hostApi);
12067
12068 uosDeviceInfos[x].DeviceName := UTF8Decode (devinf^._name);
12069 uosDeviceInfos[x].HostAPIName := UTF8Decode (apiinf^._name);
12070
12071 if x = uosDefaultDeviceIn then
12072 uosDeviceInfos[x].DefaultDevIn := True
12073 else
12074 uosDeviceInfos[x].DefaultDevIn := False;
12075
12076 if x = uosDefaultDeviceOut then
12077 uosDeviceInfos[x].DefaultDevOut := True
12078 else
12079 uosDeviceInfos[x].DefaultDevOut := False;
12080
12081 uosDeviceInfos[x].ChannelsIn := devinf^.maxInputChannels;
12082 uosDeviceInfos[x].ChannelsOut := devinf^.maxOutPutChannels;
12083 uosDeviceInfos[x].SampleRate := devinf^.defaultSampleRate;
12084 uosDeviceInfos[x].LatencyHighIn := devinf^.defaultHighInputLatency;
12085 uosDeviceInfos[x].LatencyLowIn := devinf^.defaultLowInputLatency;
12086 uosDeviceInfos[x].LatencyHighOut := devinf^.defaultHighOutputLatency;
12087 uosDeviceInfos[x].LatencyLowOut := devinf^.defaultLowOutputLatency;
12088
12089 if uosDeviceInfos[x].ChannelsIn = 0 then
12090 begin
12091 if uosDeviceInfos[x].ChannelsOut = 0 then
12092 uosDeviceInfos[x].DeviceType := 'None'
12093 else uosDeviceInfos[x].DeviceType := 'Out';
12094 end
12095 else
12096 begin
12097 if uosDeviceInfos[x].ChannelsOut = 0 then
12098 uosDeviceInfos[x].DeviceType := 'In'
12099 else uosDeviceInfos[x].DeviceType := 'In/Out';
12100 end;
12101 Inc (x);
12102 end;
12103 end;
12104end;
12105
12106function uos_GetInfoDeviceStr () : PansiChar;
12107var
12108 x : cint32;
12109 devtmp , bool1, bool2 : UTF8String;
12110begin
12111
12112 uos_GetInfoDevice ();
12113
12114 x := 0;
12115 devtmp := '';
12116
12117 while x < length (uosDeviceInfos) do
12118 begin
12119 if uosDeviceInfos[x].DefaultDevIn then bool1 := 'Yes'
12120 else bool1 := 'No';
12121 if uosDeviceInfos[x].DefaultDevOut then bool2 := 'Yes'
12122 else bool2 := 'No';
12123
12124 devtmp := devtmp +
12125
12126 'DeviceNum: ' + inttostr (uosDeviceInfos[x].DeviceNum) + ' |' +
12127 ' Name: ' + uosDeviceInfos[x].DeviceName + ' |' +
12128 ' Type: ' + uosDeviceInfos[x].DeviceType + ' |' +
12129 ' DefIn: ' + bool1 + ' |' +
12130 ' DefOut: ' + bool2 + ' |' +
12131 ' ChanIn: ' + IntToStr (uosDeviceInfos[x ].ChannelsIn)+ ' |' +
12132 ' ChanOut: ' + IntToStr (uosDeviceInfos[x].ChannelsOut) + ' |' +
12133 ' SampleRate: ' + floattostrf (uosDeviceInfos[x].SampleRate, ffFixed, 15, 0) + ' |'
12134 +
12135 ' LatencyHighIn: ' + floattostrf (uosDeviceInfos[x].LatencyHighIn, ffFixed, 15, 8) +
12136 ' |' +
12137 ' LatencyHighOut: ' + floattostrf (uosDeviceInfos[x].LatencyHighOut, ffFixed, 15, 8)
12138 +
12139 ' |' +
12140 ' LatencyLowIn: ' + floattostrf (uosDeviceInfos[x].LatencyLowIn, ffFixed, 15, 8)+
12141 ' |' +
12142 ' LatencyLowOut: ' + floattostrf (uosDeviceInfos[x].LatencyLowOut, ffFixed, 15, 8)+
12143 ' |' +
12144 ' HostAPI: ' + uosDeviceInfos[x].HostAPIName;
12145 if x < length (uosDeviceInfos)-1 then devtmp := devtmp + #13#10;
12146 Inc (x);
12147 end;
12148 result := pansichar ( devtmp + ' ' );
12149 // }
12150end;
12151{$endif}
12152
12153{$IF DEFINED (Java)}
12154procedure Tuos_Player.beginprocjava ();
12155begin
12156 (PEnv^^).CallVoidMethod (PEnv,Obj,BeginProc) ;
12157end;
12158
12159procedure Tuos_Player.endprocjava ();
12160begin
12161 (PEnv^^).CallVoidMethod (PEnv,Obj,EndProc) ;
12162end;
12163
12164procedure Tuos_Player.LoopBeginProcjava ();
12165begin
12166 (PEnv^^).CallVoidMethod (PEnv,Obj,LoopBeginProc) ;
12167end;
12168
12169procedure Tuos_Player.LoopEndProcjava ();
12170begin
12171 (PEnv^^).CallVoidMethod (PEnv,Obj,LoopEndProc) ;
12172end;
12173
12174procedure Tuos_DSP.LoopProcjava ();
12175begin
12176 // todo
12177end;
12178
12179procedure Tuos_InStream.LoopProcjava ();
12180begin
12181 // todo
12182end;
12183
12184procedure Tuos_OutStream.LoopProcjava ();
12185begin
12186 // todo
12187end;
12188{$endif}
12189
12190{$IF DEFINED (webstream)}
12191procedure Tuos_InStream.UpdateIcyMetaInterval;
12192begin
12193 if Data.HandleSt<>nil then
12194 mpg123_param (Data.HandleSt, MPG123_ICY_INTERVAL, httpget.IcyMetaInt, 0);
12195end;
12196{$endif}
12197
12198function AssignDefaultForUOSData: Tuos_Data;
12199var
12200 i: Integer;
12201begin
12202 with Result do
12203 begin
12204 Enabled := False;
12205 TypePut := -1;
12206 //nothing
12207 Seekable := False;
12208 Status := 0;
12209 // no data
12210 SetLength (Buffer,0);
12211 SetLength (MemoryBuffer,0);
12212 MemoryStream := Nil;
12213 posmem := 0;
12214
12215 {$IF DEFINED (opus)}
12216 SetLength (BufferTMP,0);
12217 {$endif}
12218
12219 DSPVolumeIndex := -1;
12220 DSPNoiseIndex := -1;
12221 VLeft := 0;
12222
12223 VRight := 0;
12224
12225 hasfilters := false;
12226
12227 nbfilters := 0;
12228
12229 incfilters := 0;
12230
12231 PositionEnable := 0;
12232 LevelEnable := 0;
12233 LevelLeft := 0;
12234 LevelRight := 0;
12235 levelArrayEnable := 0;
12236
12237 SampleRate := 44100;
12238 {$IF DEFINED (synthesizer)}
12239 freqLsine := 440;
12240 freqRsine := freqLsine;
12241 dursine := 0;
12242 posdursine := 0;
12243 harmonic := 0;
12244 {$endif}
12245 SamplerateRoot := SampleRate;
12246
12247 Wantframes := 0;
12248 OutFrames := 0;
12249
12250 SampleFormat := -1;
12251 // default
12252 Channels := -1;
12253 // default
12254
12255 HandleSt := Nil;
12256 {$IF DEFINED (opus)}
12257 HandleOP := Nil;
12258 {$endif}
12259
12260 Filename := '';
12261 Title := '';
12262 Copyright := '';
12263 Software := '';
12264 Artist := '';
12265 Comment := '';
12266 Date := '';
12267 for i:= 0 to High (Tag) do
12268 Tag[i] := #0;
12269 Album := '';
12270 Genre := '';
12271 HDFormat := 0;
12272 Frames := 0;
12273 Sections := 0;
12274 Encoding := -1;
12275 // unknow
12276 bitrate := -1;
12277 // unknow
12278 Length := 0;
12279 LibOpen := -1;
12280 // nothing open
12281 Ratio := 0;
12282
12283 BPM := 0;
12284
12285 numbuf := -1;
12286 //default
12287
12288 Output := -1;
12289 //error
12290
12291 Position := 0;
12292 Poseek := 0;
12293 end;
12294end;
12295
12296constructor Tuos_FFT.Create;
12297var
12298 i: Integer;
12299begin
12300 inherited;
12301
12302 AlsoBuf := False;
12303
12304 TypeFilterL := 0;
12305 LowFrequencyL := 0;
12306 HighFrequencyL := 0;
12307 GainL := 0;
12308
12309 for i:= 0 to High (a3) do
12310 a3[i] := 0;
12311 for i:= 0 to High (a32) do
12312 a32[i] := 0;
12313
12314 for i:= 0 to High (TArray01) do
12315 begin
12316 b2[i] := 0;
12317 x0[i] := 0;
12318 x1[i] := 0;
12319 y0[i] := 0;
12320 y1[i] := 0;
12321 b22[i] := 0;
12322 x02[i] := 0;
12323 x12[i] := 0;
12324 y02[i] := 0;
12325 y12[i] := 0;
12326 end;
12327
12328 C := 0;
12329 D := 0;
12330 C2 := 0;
12331 D2 := 0;
12332
12333 TypeFilterR := 0;
12334 LowFrequencyR := 0;
12335 HighFrequencyR := 0;
12336 GainR := 0;
12337 for i:= 0 to High (a3r) do
12338 a3r[i] := 0;
12339 for i:= 0 to High (a32r) do
12340 a32r[i] := 0;
12341
12342 for i:= 0 to High (TArray01) do
12343 begin
12344 b2r[i] := 0;
12345 x0r[i] := 0;
12346 x1r[i] := 0;
12347 y0r[i] := 0;
12348 y1r[i] := 0;
12349 b22r[i] := 0;
12350 x02r[i] := 0;
12351 x12r[i] := 0;
12352 y02r[i] := 0;
12353 y12r[i] := 0;
12354 end;
12355
12356 Cr := 0;
12357 Dr := 0;
12358 C2r := 0;
12359 D2r := 0;
12360
12361 levelstring := '';
12362
12363 {$IF DEFINED (noiseremoval)}
12364 FNoise := Nil;
12365 {$endif}
12366end;
12367
12368constructor Tuos_DSP.Create;
12369begin
12370 inherited;
12371
12372 Enabled := False;
12373 BefFunc := Nil;
12374 AftFunc := Nil;
12375 EndFunc := Nil;
12376 LoopProc := Nil;
12377 fftdata := Nil;
12378end;
12379
12380constructor Tuos_InStream.Create;
12381begin
12382 inherited;
12383
12384 Data := AssignDefaultForUOSData;
12385 SetLength (DSP,0);
12386
12387 {$IF DEFINED (neaac)}
12388 AACI := Nil;
12389 {$endif}
12390
12391 {$IF DEFINED (cdrom)}
12392 pCD := Nil;
12393 {$endif}
12394
12395 {$IF DEFINED (webstream)}
12396 httpget := Nil;
12397
12398 InHandle := 0;
12399 OutHandle := 0;
12400
12401 InPipe := Nil;
12402 OutPipe := Nil;
12403 {$ENDIF}
12404
12405 {$IF DEFINED (portaudio)}
12406 with PAParam do
12407 begin
12408 device := 0;
12409 channelCount := 0;
12410 sampleFormat := Nil;
12411 suggestedLatency := 0;
12412 hostApiSpecificStreamInfo := Nil;
12413 end;
12414 {$endif}
12415
12416 LoopProc := Nil;
12417end;
12418
12419constructor Tuos_OutStream.Create;
12420{$IF DEFINED (shout)}
12421var
12422 i: integer;
12423{$endif}
12424begin
12425 inherited;
12426
12427 Data := AssignDefaultForUOSData;
12428 BufferOut := Nil;
12429 SetLength (DSP,0);
12430
12431 {$IF DEFINED (portaudio)}
12432 with PAParam do
12433 begin
12434 //TODO: check if the default settings are ok
12435 device := 0;
12436 channelCount := 0;
12437 sampleFormat := Nil;
12438 suggestedLatency := 0;
12439 hostApiSpecificStreamInfo := Nil;
12440 end;
12441 {$endif}
12442
12443 {$IF DEFINED (shout)}
12444 encoder := Nil;
12445 for i:= 0 to High (cbits) do
12446 cbits[i] := 0;
12447 //byte
12448 {$endif}
12449
12450 with FileBuffer do
12451 begin
12452 ERROR := 0;
12453 wSamplesPerSec := 44100;
12454 wBitsPerSample := 32;
12455 wChannels := 2;
12456 FileFormat := -1;
12457 Data := Nil;
12458 DataMS := Nil;
12459 end;
12460 LoopProc := Nil;
12461
12462 MemorySteamOut := Nil;
12463
12464 {$IF DEFINED (Java)}
12465 // procedure LoopProcjava;
12466 {$endif}
12467end;
12468
12469constructor Tuos_Plugin.Create;
12470begin
12471 inherited;
12472
12473 Enabled := False;
12474 Name := '';
12475
12476 {$IF DEFINED (windows)}
12477 PlugHandle := 0;
12478 {$else}
12479 PlugHandle := Nil;
12480 {$endif}
12481
12482 {$IF DEFINED (bs2b) or DEFINED (soundtouch)}
12483 Abs2b := Nil;
12484 PlugFunc := Nil;
12485 {$endif}
12486 param1 := -1;
12487 param2 := -1;
12488 param3 := -1;
12489 param4 := -1;
12490 param5 := -1;
12491 param6 := -1;
12492 param7 := -1;
12493 param8 := -1;
12494
12495 SetLength (Buffer,0);
12496end;
12497
12498constructor Tuos_Init.Create;
12499begin
12500 {$IF DEFINED (portaudio)}
12501 DefDevOut := -1;
12502 DefDevOutInfo := Nil;
12503 DefDevOutAPIInfo := Nil;
12504 DefDevIn := -1;
12505 DefDevInInfo := Nil;
12506 DefDevInAPIInfo := Nil;
12507 {$endif}
12508
12509 TDummyThread.Create (false);
12510 evGlobalPause := RTLEventCreate;
12511
12512 SetExceptionMask (GetExceptionMask + [exZeroDivide] + [exInvalidOp] +
12513 [exDenormalized] + [exOverflow] + [exUnderflow] + [exPrecision]);
12514 uosLoadResult.PAloadERROR := -1;
12515 uosLoadResult.PCloadERROR := -1;
12516 uosLoadResult.SFloadERROR := -1;
12517 uosLoadResult.BSloadERROR := -1;
12518 uosLoadResult.STloadERROR := -1;
12519 uosLoadResult.MPloadERROR := -1;
12520 uosLoadResult.AAloadERROR := -1;
12521 uosLoadResult.OPloadERROR := -1;
12522 uosLoadResult.XMloadERROR := -1;
12523 uosLoadResult.PAinitError := -1;
12524 uosLoadResult.MPinitError := -1;
12525
12526 PA_FileName := Nil;
12527 // PortAudio
12528 SF_FileName := Nil;
12529 // SndFile
12530 MP_FileName := Nil;
12531 // Mpg123
12532 AA_FileName := Nil;
12533 // Faad
12534 M4_FileName := Nil;
12535 // Mp4ff
12536 OF_FileName := Nil;
12537 // opusfile
12538 XM_FileName := Nil;
12539 // XMP
12540 Plug_ST_FileName := Nil;
12541 // Plugin SoundTouch
12542 Plug_BS_FileName := Nil;
12543 // Plugin bs2b
12544end;
12545
12546constructor Tuos_Player.create ();
12547begin
12548 evPause := RTLEventCreate;
12549
12550 Index := -1;
12551 //default for independent instance
12552
12553 isAssigned := true;
12554 isGlobalPause := false;
12555 intobuf := false;
12556 NLooped := 0;
12557 NoFree := False;
12558 status := -1;
12559 BeginProc := Nil;
12560 EndProc := Nil;
12561 EndProcOnly := Nil;
12562 loopBeginProc := Nil;
12563 loopEndProc := Nil;
12564
12565 thethread := Nil;
12566 SetLength (StreamIn,0);
12567 SetLength (StreamOut,0);
12568 SetLength (PlugIn,0);
12569
12570 {$IF DEFINED (Java)}
12571 PEnv := Nil;
12572 Obj := Nil;
12573 {$endif}
12574end;
12575
12576{$IF DEFINED (mse)}
12577{$else}
12578procedure TuosThread.DoTerminate;
12579begin
12580 {$IF FPC_FULLVERSION>=20701}
12581 //Terminate the thread the calls places into the queuelist will be removed
12582 RemoveQueuedEvents (Self);
12583 {$ENDIF}
12584 //notice that is no longer valid (for safe destroy event of theparent)
12585 Tuos_Player (theparent).thethread := Nil;
12586 //execute player destroy
12587 FreeAndNil (theparent);
12588end;
12589 {$endif}
12590
12591destructor Tuos_Player.Destroy;
12592var
12593 x: cint32;
12594begin
12595
12596 if thethread <> nil then
12597 begin
12598 {$ifdef mse}
12599 thethread.terminate ();
12600 application.waitforthread (thethread);
12601 //calls unlockall ()/relockall in order to avoid possible deadlock
12602 thethread.destroy ();
12603 {$endif}
12604 end;
12605
12606 if assigned (evPause) then RTLeventdestroy (evPause);
12607
12608 if length (StreamOut) > 0 then
12609 for x := 0 to high (StreamOut) do
12610 freeandnil (StreamOut[x]);
12611
12612 if length (StreamIn) > 0 then
12613 for x := 0 to high (StreamIn) do
12614 freeandnil (StreamIn[x]);
12615
12616 if length (Plugin) > 0 then
12617 for x := 0 to high (Plugin) do
12618 freeandnil (Plugin[x]);
12619
12620 // Note: if Index = -1 is an independent instance
12621 if Index <> -1 then
12622 begin
12623 // now notice that player is really free
12624 uosPlayersStat[Index] := -1;
12625 uosPlayers[Index] := Nil;
12626 end;
12627
12628 inherited Destroy;
12629
12630end;
12631
12632destructor Tuos_DSP.Destroy;
12633begin
12634 if assigned (fftdata) then
12635 begin
12636 {$IF DEFINED (noiseremoval)}
12637 if assigned (fftdata.FNoise) then FreeAndNil (fftdata.FNoise);
12638 {$endif}
12639 FreeandNil (fftdata);
12640 end;
12641
12642 inherited Destroy;
12643end;
12644
12645destructor Tuos_InStream.Destroy;
12646var
12647 x: cint32;
12648begin
12649 {$IF DEFINED (neaac)}
12650 if assigned (AACI) then
12651 begin
12652 if assigned (AACI.fsStream) then
12653 begin
12654 freeandnil (AACI.fsStream);
12655 sleep (100);
12656 end;
12657 freeandnil (AACI);
12658 sleep (100);
12659 end;
12660 {$endif}
12661 if assigned (Data.MemoryStream) then
12662 freeandnil (Data.MemoryStream);
12663
12664 if length (DSP) > 0 then
12665 for x := 0 to high (DSP) do
12666 freeandnil (DSP[x]);
12667
12668 inherited Destroy;
12669
12670end;
12671
12672destructor Tuos_OutStream.Destroy;
12673var
12674 x: cint32;
12675begin
12676 if length (DSP) > 0 then
12677 for x := 0 to high (DSP) do
12678 freeandnil (DSP[x]);
12679
12680 inherited Destroy;
12681end;
12682
12683procedure Tuos_Init.unloadlibCust (PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
12684// Custom Unload libraries... if true, then unload the library. You may unload what and when you want...
12685begin
12686 {$IF DEFINED (portaudio)}
12687 if PortAudio = true then Pa_Unload ();
12688 {$endif}
12689 {$IF DEFINED (sndfile)}
12690 if SndFile = true then sf_Unload ();
12691 {$endif}
12692 {$IF DEFINED (mpg123)}
12693 if Mpg123 = true then mp_Unload ();
12694 {$endif}
12695 {$IF DEFINED (xmp)}
12696 if xmp = true then xmp_Unload ();
12697 {$endif}
12698 {$IF DEFINED (fdkaac)}
12699 if fdkaac = true then ad_Unload ();
12700 {$endif}
12701 {$IF DEFINED (neaac)}
12702 if AAC = True then aa_Unload ();
12703 {$endif}
12704 {$IF DEFINED (opus)}
12705 if opus = True then
12706 begin
12707 of_Unload ();
12708 // op_Unload ();
12709 end;
12710 {$endif}
12711end;
12712
12713procedure uos_Free ();
12714begin
12715 uos_unloadlib ();
12716
12717 if assigned (uosInit) then
12718 begin
12719 if assigned (uosInit.evGlobalPause) then
12720 RTLeventdestroy (uosInit.evGlobalPause);
12721 freeandnil (uosInit);
12722 end;
12723end;
12724
12725initialization
12726SetLength (tempoutmemory,0);
12727SetLength (uosPlayers,0);
12728SetLength (uosPlayersStat,0);
12729SetLength (uosLevelArray,0);
12730SetLength (uosDeviceInfos,0);
12731uosInit := Nil;
12732
12733end.
Note: See TracBrowser for help on using the repository browser.