Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
165 serge 1
//
2
//   This file is part of the AC97 mp3 player.
3
//   (C) copyright Serge 2006
4
//   email: infinity_sound@mail.ru
5
//
6
//   This program is free software; you can redistribute it and/or modify
7
//   it under the terms of the GNU General Public License as published by
8
//   the Free Software Foundation; either version 2 of the License, or
9
//   (at your option) any later version.
10
//
11
//   This program is distributed in the hope that it will be useful,
12
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
//   GNU General Public License for more details.
15
 
16
#include "kolibri.h"
17
#include "stdio.h"
18
#include "string.h"
19
#include "ac97wav.h"
20
#include "mp3dec/mp3dec.h"
21
 
22
void thread_proc();
23
void touch(char *buf, int size);
24
 
25
extern char *__argv;
26
 
27
//extern char __path;
28
 
29
/*****      for debug output only
30
char formats[37][12] =
31
{ "PCM_ALL",
32
  "PCM_2_16_48","PCM_1_16_48","PCM_2_16_44","PCM_1_16_44",
33
  "PCM_2_16_32","PCM_1_16_32","PCM_2_16_24","PCM_1_16_24",
34
  "PCM_2_16_22","PCM_1_16_22","PCM_2_16_16","PCM_1_16_16",
35
  "PCM_2_16_12","PCM_1_16_12","PCM_2_16_11","PCM_1_16_11",
36
  "PCM_2_16_8","PCM_1_16_8","PCM_2_8_48","PCM_1_8_48",
37
  "PCM_2_8_44","PCM_1_8_44","PCM_2_8_32","PCM_1_8_32",
38
  "PCM_2_8_24","PCM_1_8_24","PCM_2_8_22","PCM_1_8_22",
39
  "PCM_2_8_16","PCM_1_8_16","PCM_2_8_12","PCM_1_8_12",
40
  "PCM_2_8_11","PCM_1_8_11","PCM_2_8_8","PCM_1_8_8"
41
};
42
*******/
43
 
44
DWORD hDrv;
45
DWORD hSound;
46
DWORD hBuff;
47
DWORD event[2];
48
 
49
CTRL_INFO info;
50
 
51
FILEINFO   fileinfo;
52
 
53
int m_vol;
54
DWORD status;
55
DWORD offset;
56
DWORD first_sync;
57
 
58
char *testbuff;
59
char *outbuf;
60
char *inpbuf;
61
int inpsize;
62
int outsize;
63
 
64
char srv_name[] = "INFINITY";
65
char srv_intel[] = "SOUND";
66
char header[] = "AC97 MP3 player";
67
char buttons_text[]=" Play    Stop     <<      >>     Vol-    Vol+";
68
 
69
MPEG_DECODE_INFO mpginfo;
70
MPEG_DECODE_PARAM param;
71
 
72
void (*snd_play)();
73
 
74
void draw_window()
75
{
76
   BeginDraw();
77
 
78
   DrawWindow(100,100,299,72,0x404040,3,0,0,0);
79
 
80
   make_button(7,24,45,13, 0x10|BT_NORMAL,0x808080);
81
   make_button(56,24,45,13, 0x11|BT_NORMAL,0x808080);
82
   make_button(104,24,45,13, 0x12|BT_NORMAL,0x808080);
83
   make_button(152,24,45,13, 0x13|BT_NORMAL,0x808080);
84
   make_button(200,24,45,13, 0x14|BT_NORMAL,0x808080);
85
   make_button(248,24,45,13, 0x15|BT_NORMAL,0x808080);
86
 
87
   make_button(7,41,286,11, 0x30|BT_HIDE|BT_NOFRAME,0x404040);
88
   draw_bar(7,41,286,11,0x404040);
89
 
90
   draw_bar(7,55,286,11,0x404040);
91
   write_text(12,58,0x004000|FONT0, __argv, strlen(__argv));
92
   write_text(11,57,0x00FF20|FONT0, __argv, strlen(__argv));
93
 
94
   write_text(8,8,0xFFFFFF|FONT0, header, strlen(header));
95
   write_text(12,28,0x404040|FONT0,buttons_text,strlen(buttons_text));
96
   write_text(11,27,0xA0FFA0|FONT0,buttons_text,strlen(buttons_text));
97
 
98
   EndDraw();
99
};
100
 
101
void draw_progress_bar()
102
{  DWORD x;
103
   x = 286.0f * (float)offset/(float)fileinfo.size;
104
   if(x==0) return;
105
   draw_bar(7,41,x,11,0xA0A0A0);
106
   draw_bar(x+7,41,286-x,11,0x404040);
107
};
108
 
109
void debug_out_str(char* str)
110
{
111
  while (*str != 0)
112
  {
113
    debug_out(*str);
114
    str++;
115
  }
116
}
117
 
118
int main()      //int argc, char *argv[])
119
{ DWORD fmt;
120
   char *thread_stack;
121
   DWORD r_bytes;
122
   int retval;
123
 
124
   InitHeap(1024*1024);
125
   if(get_fileinfo(__argv, &fileinfo)==FILE_NOT_FOUND)
126
      return 0;
127
 
128
   if((hDrv=GetService(srv_intel))==0)
129
     return 0;
130
 
131
   if ((hSound=GetService(srv_name))==0)
132
     return 0;
133
 
134
   GetDevInfo(hDrv, &info);
135
 
136
   m_vol = GetMasterVol(hDrv,&m_vol);
137
   if (m_vol > 85)
138
   { m_vol = 85;
139
      SetMasterVol(hDrv,m_vol);
140
   };
141
 
142
   _asm {fninit};
143
   mp3DecodeInit();
144
 
145
   testbuff = UserAlloc(4096);
146
   get_fileinfo(__argv, &fileinfo);
147
   offset = 0;
148
   retval=read_file (__argv,testbuff,0,2048,&r_bytes);
149
   if (retval) return 0;
150
 
151
   fmt = test_wav((WAVEHEADER*)testbuff);
152
   if (fmt != 0)
153
   {
154
     snd_play = &play_wave;
155
     outbuf = UserAlloc(32*1024);
156
     touch(outbuf, 32768);
157
     offset = 44;
158
   }
159
   else
160
   {  fmt = test_mp3(testbuff);
161
       if(fmt ==0) return 0;
162
       snd_play = &play_mp3;
163
 
164
       inpsize = mpginfo.maxInputSize*30;
165
       inpbuf =  UserAlloc(inpsize);
166
       touch(inpbuf, inpsize);
167
       outsize = mpginfo.outputSize*30+0x10000;
168
       outbuf = UserAlloc(outsize);
169
       touch(outbuf, outsize);
170
       first_sync = offset;
171
   };
172
 
173
   status = ST_PLAY;
174
 
175
   hBuff = CreateBuffer(hSound,fmt);
176
   if (hBuff == 0) return 0;
177
   thread_stack = UserAlloc(4096);
178
   thread_stack+=4092;
179
 
180
   CreateThread(thread_proc, thread_stack);
181
 
182
   while(1)
183
   {  delay(10);
184
      switch(status)
185
      {  case ST_PLAY:
186
           snd_play();
187
           continue;
188
 
189
         case ST_STOP:
190
           StopBuffer(hSound, hBuff);
191
           status = ST_DONE;
192
           continue;
193
 
194
         case ST_EXIT:
195
           StopBuffer(hSound, hBuff);
196
           DestroyBuffer(hSound, hBuff);
197
           return 0;
198
      };
199
   };
200
   return 0;
201
};
202
 
203
void touch(char *buf, int size)
204
{ int i;
205
    for ( i = 0;i < size; i+=4096)
206
      buf[i] = 0;
207
};
208
 
209
DWORD test_mp3(char *buf)
210
{  int retval;
211
    int sync;
212
    WAVEHEADER whdr;
213
    DWORD r_bytes=2048;
214
 
215
    for (;;)
216
    {
217
    	  if (!mp3FindSync(buf, 2048, &sync))
218
     	    offset+= 2048;
219
        else break;
220
 
221
        if (offset >= fileinfo.size || offset >= 102400)
222
            return 0;
223
 
224
        retval = read_file (__argv,buf,offset,2048,&r_bytes);
225
    	  if(retval != 0)  return 0;
226
	  };
227
    offset+=sync;
228
    retval = read_file (__argv,buf,offset,2048,&r_bytes);
229
 	  if(retval != 0) return 0;
230
 
231
  	mp3GetDecodeInfo(buf, r_bytes, &mpginfo, 1);
232
    whdr.riff_id = 0x46464952;
233
    whdr.riff_format = 0x45564157;
234
    whdr.wFormatTag = 0x01;
235
    whdr.nSamplesPerSec = mpginfo.frequency;
236
    whdr.nChannels = mpginfo.channels;
237
    whdr.wBitsPerSample = mpginfo.bitsPerSample;
238
 
239
    return test_wav(&whdr);
240
};
241
void wave_out(char* buff)
242
{ DWORD ev[2];
243
 
244
   GetNotify(&ev[0]);
245
   SetBuffer(hSound,hBuff,buff,ev[1],0x8000);
246
}
247
 
248
void play_mp3()
249
{  int retval;
250
    DWORD r_bytes;
251
    char *inpPtr;
252
    char *outPtr;
253
    int inpBytes;
254
    int totalout;
255
 
256
    offset = first_sync;
257
 
258
    retval = read_file (__argv,inpbuf,offset,inpsize,&r_bytes);
259
 	  if(retval != 0)
260
 	  {  status =  ST_STOP;
261
 	      return ;
262
    };
263
    offset+=inpsize;
264
 
265
    mp3DecodeStart(inpbuf, inpsize);
266
 
267
    inpPtr = inpbuf+mpginfo.skipSize;
268
    inpBytes = inpsize-mpginfo.skipSize;
269
    outPtr = outbuf;
270
    totalout=0;
271
 
272
    memset(outbuf,0,0x10000);
273
    SetBuffer(hSound,hBuff,outbuf,0,0x10000);
274
    PlayBuffer(hSound, hBuff);
275
 
276
    _asm { fninit }
277
 
278
    while(1)
279
    { if(status!=ST_PLAY)
280
             break;
281
 
282
      for(;;)
283
      { param.inputBuf	= inpPtr;
284
	       param.inputSize	= inpBytes;
285
     	   param.outputBuf	= outPtr;
286
 
287
    	   if(!mp3DecodeFrame(¶m))
288
            if( mp3GetLastError()== MP3_ERROR_OUT_OF_BUFFER)
289
              break;
290
 
291
         inpPtr += param.inputSize;
292
		     inpBytes -= param.inputSize;
293
         outPtr+=param.outputSize;
294
         totalout+=param.outputSize;
295
      };
296
		  memmove(inpbuf, inpPtr, inpBytes);
297
  	  retval = read_file(__argv, &inpbuf[inpBytes],offset, inpsize-inpBytes, &r_bytes);
298
      offset+=r_bytes;
299
 
300
	    if (r_bytes== 0)  break;
301
 
302
		  inpPtr = inpbuf;
303
		  inpBytes += r_bytes;
304
	    if(totalout < 32768) continue;
305
 
306
	    outPtr = outbuf;
307
	    while (totalout > 32768)
308
     { wave_out(outPtr);
309
	      totalout-=0x8000;
310
	      outPtr+=0x8000;
311
      };
312
      memmove(outbuf,outPtr, totalout);
313
      outPtr = outbuf+totalout;
314
    };
315
    if(status != ST_EXIT)
316
    status =  ST_STOP;
317
};
318
 
319
void play_wave()
320
{
321
   int retval;
322
   int remain;
323
   int i;
324
 
325
   offset = 44;
326
 
327
   read_file (__argv,outbuf,offset,32*1024,0);
328
   offset+=32*1024;
329
   SetBuffer(hSound,hBuff,outbuf,0,0x8000);
330
 
331
   read_file (__argv,outbuf,offset,32*1024,0);
332
   offset+=32*1024;
333
   SetBuffer(hSound,hBuff,outbuf,0x8000,0x8000);
334
 
335
   PlayBuffer(hSound, hBuff);
336
 
337
   retval = 0;
338
   while(1)
339
   {
340
     if(status!=ST_PLAY)
341
       break;
342
 
343
     GetNotify(&event[0]);
344
     if(retval == FILE_EOF)
345
       break;
346
     remain = fileinfo.size-offset;
347
     if(remain >=32768)
348
     { retval = read_file (__argv,outbuf,offset,32*1024,0);
349
       offset+=32*1024;
350
       SetBuffer(hSound,hBuff,outbuf,event[1],0x8000);
351
       continue;
352
     };
353
     if(remain == 0)
354
     { retval = FILE_EOF;
355
       continue;
356
     };
357
     read_file (__argv,outbuf,offset,remain,0);
358
     for(i=remain;i<32768;i++)
359
       outbuf[i] = 0;
360
     SetBuffer(hSound,hBuff,outbuf,event[1],0x8000);
361
     retval= FILE_EOF;
362
   };
363
 
364
   if(status != ST_EXIT)
365
    status =  ST_STOP;
366
};
367
 
368
void snd_stop()
369
{
370
  StopBuffer(hSound, hBuff);
371
};
372
 
373
void thread_proc()
374
{ int evnt;
375
   int pos;
376
   int key;
377
 
378
  _asm { fninit };
379
 
380
 
381
  draw_window();
382
 
383
  while(1)
384
  {  if(status==ST_PLAY)
385
      {  draw_progress_bar();
386
          evnt = wait_for_event(80);
387
       //   debug_out_str("BIG ERROR...\x0D\x0A\x00");
388
      }
389
     else
390
        evnt = wait_for_event_infinite();
391
 
392
    switch(evnt)
393
    {
394
      case EV_REDRAW:
395
        draw_window();
396
        break;
397
 
398
      case EV_KEY:
399
        key = get_key();
400
        if(key==27)
401
        {   status = ST_EXIT;
402
            exit();
403
        };
404
        if((key==45)||key==54)
405
        { if(m_vol > 0)
406
          { m_vol--;
407
            SetMasterVol(hDrv,m_vol);
408
          };
409
          break;
410
        };
411
        if((key==61)||key==56)
412
        { if(m_vol < 90)
413
          { m_vol++;
414
            SetMasterVol(hDrv,m_vol);
415
          };
416
        };
417
        break;
418
 
419
      case EV_BUTTON:
420
        switch(get_button_id())
421
        {  case 1:
422
             status = ST_EXIT;
423
             exit();
424
             break;
425
 
426
           case 0x10:
427
             status = ST_PLAY;
428
             continue;
429
 
430
           case 0x11:
431
             status = ST_STOP;
432
             break;
433
//           case 0x12:
434
//           case 0x13:
435
           case 0x14:
436
             if(m_vol > 0)
437
             { m_vol--;
438
               SetMasterVol(hDrv,m_vol);
439
             };
440
             break;
441
 
442
           case 0x15:
443
             if(m_vol < 90)
444
             { m_vol++;
445
               SetMasterVol(hDrv,m_vol);
446
             };
447
             break;
448
 
449
           case 0x30:
450
            if(status==ST_DONE)
451
              break;
452
            if(snd_play == play_mp3)
453
              continue;
454
            pos = (GetMousePos(REL_WINDOW)>>16)-7;
455
            offset = ((fileinfo.size-44)/286*pos+44)&0xFFFFFFFC;
456
            draw_progress_bar();
457
            break;
458
        };
459
    };
460
  };
461
};
462
 
463
DWORD test_wav(WAVEHEADER *hdr)
464
{
465
  if(hdr->riff_id != 0x46464952)
466
    return 0;
467
 
468
  if(hdr->riff_format != 0x45564157)
469
    return 0;
470
 
471
  if (hdr->wFormatTag != 0x01)
472
    return 0;
473
 
474
  switch(hdr->nSamplesPerSec)
475
  { case 48000:
476
      switch (hdr->nChannels)
477
      {  case 1:
478
           if(hdr->wBitsPerSample == 16)
479
             return PCM_1_16_48;
480
           else
481
             return PCM_1_8_48;
482
 
483
         case 2:
484
           if(hdr->wBitsPerSample == 16)
485
             return PCM_2_16_48;
486
           else
487
             return PCM_2_8_48;
488
      };
489
 
490
    case 44100:
491
      switch (hdr->nChannels)
492
      {  case 1:
493
           if(hdr->wBitsPerSample == 16)
494
             return PCM_1_16_44;
495
           else
496
             return PCM_1_8_44;
497
 
498
         case 2:
499
           if(hdr->wBitsPerSample == 16)
500
             return PCM_2_16_44;
501
           else
502
             return PCM_2_8_44;
503
      };
504
 
505
    case 32000:
506
      switch (hdr->nChannels)
507
      {  case 1:
508
           if(hdr->wBitsPerSample == 16)
509
             return PCM_1_16_32;
510
           else
511
             return PCM_1_8_32;
512
 
513
         case 2:
514
           if(hdr->wBitsPerSample == 16)
515
             return PCM_2_16_32;
516
           else
517
             return PCM_2_8_32;
518
      };
519
 
520
    case 24000:
521
      switch (hdr->nChannels)
522
      {  case 1:
523
           if(hdr->wBitsPerSample == 16)
524
             return PCM_1_16_24;
525
           else
526
             return PCM_1_8_24;
527
 
528
         case 2:
529
           if(hdr->wBitsPerSample == 16)
530
             return PCM_2_16_24;
531
           else
532
             return PCM_2_8_24;
533
      };
534
 
535
    case 22050:
536
      switch (hdr->nChannels)
537
      {  case 1:
538
           if(hdr->wBitsPerSample == 16)
539
             return PCM_1_16_22;
540
           else
541
             return PCM_1_8_22;
542
 
543
         case 2:
544
           if(hdr->wBitsPerSample == 16)
545
             return PCM_2_16_22;
546
           else
547
             return PCM_2_8_22;
548
      };
549
 
550
    case 16000:
551
      switch (hdr->nChannels)
552
      {  case 1:
553
           if(hdr->wBitsPerSample == 16)
554
             return PCM_1_16_16;
555
           else
556
             return PCM_1_8_16;
557
 
558
         case 2:
559
           if(hdr->wBitsPerSample == 16)
560
             return PCM_2_16_16;
561
           else
562
             return PCM_2_8_16;
563
      };
564
 
565
    case 12000:
566
      switch (hdr->nChannels)
567
      {  case 1:
568
           if(hdr->wBitsPerSample == 16)
569
             return PCM_1_16_12;
570
           else
571
             return PCM_1_8_12;
572
 
573
         case 2:
574
           if(hdr->wBitsPerSample == 16)
575
             return PCM_2_16_12;
576
           else
577
             return PCM_2_8_12;
578
      };
579
 
580
    case 11025:
581
      switch (hdr->nChannels)
582
      {  case 1:
583
           if(hdr->wBitsPerSample == 16)
584
             return PCM_1_16_11;
585
           else
586
             return PCM_1_8_11;
587
 
588
         case 2:
589
           if(hdr->wBitsPerSample == 16)
590
             return PCM_2_16_11;
591
           else
592
             return PCM_2_8_11;
593
      };
594
 
595
    case 8000:
596
      switch (hdr->nChannels)
597
      {  case 1:
598
           if(hdr->wBitsPerSample == 16)
599
             return PCM_1_16_8;
600
           else
601
             return PCM_1_8_8;
602
 
603
         case 2:
604
           if(hdr->wBitsPerSample == 16)
605
             return PCM_2_16_8;
606
           else
607
             return PCM_2_8_8;
608
      };
609
      default:
610
        return 0;
611
  };
612
};
613
 
614
void delay (int val)
615
{
616
  _asm
617
 {   mov   eax,5
618
      mov   ebx, [val]
619
      int   0x40
620
  };
621
}
622
 
623
int wait_for_event(int time)
624
{ int retval;
625
  _asm
626
 {  mov  eax,23
627
     mov  ebx,[time]
628
     int  0x40
629
     mov [retval], eax
630
 };
631
 return retval;
632
};
633
 
634
int wait_for_event_infinite()
635
{ int retval;
636
  _asm
637
  {  mov  eax,10
638
      int  0x40
639
      mov [retval], eax
640
  };
641
  return retval;
642
};
643
 
644
void BeginDraw()
645
{_asm
646
 { mov   eax,12
647
    mov   ebx, 1
648
    int   0x40
649
  };
650
};
651
 
652
void EndDraw()
653
{ _asm
654
 { mov   eax,12
655
    mov   ebx, 2
656
    int   0x40
657
  };
658
};
659
 
660
void * __cdecl memmove ( void * dst, const void * src, size_t count)
661
{ void * ret = dst;
662
 
663
  if (dst <= src || (char *)dst >= ((char *)src + count))
664
  {
665
      while (count--)
666
      { *(char *)dst = *(char *)src;
667
          dst = (char *)dst + 1;
668
          src = (char *)src + 1;
669
      }
670
   }
671
   else
672
    {
673
        dst = (char *)dst + count - 1;
674
        src = (char *)src + count - 1;
675
         while (count--)
676
          {  *(char *)dst = *(char *)src;
677
              dst = (char *)dst - 1;
678
              src = (char *)src - 1;
679
          }
680
    }
681
    return(ret);
682
};
683
 
684
 
685
 
686
 
687
//   debug_out_str(formats[fmt]);
688
//   debug_out_str("\x0D\x0A\x00");
689
 
690
//   debug_out_str("pci cmd: ");
691
//   debug_out_hex(info.pci_cmd);
692
//   debug_out_str("\x0D\x0A\x00");
693
 
694
//   debug_out_str("irq line: ");
695
//   debug_out_hex(info.irq);
696
//   debug_out_str("\x0D\x0A\x00");
697
 
698
//   debug_out_str("global control: ");
699
//   debug_out_hex(info.glob_cntrl);
700
//   debug_out_str("\x0D\x0A\x00");
701
 
702
//   debug_out_str("global status:  ");
703
//   debug_out_hex(info.glob_sta);
704
//   debug_out_str("\x0D\x0A\x00");
705
 
706
 
707
  // call _print_volume
708
 
709
//   debug_out_hex(whdr.nChannels);
710
//   debug_out_str("\x0D\x0A\x00");
711
//   debug_out_hex(whdr.nSamplesPerSec);
712
//   debug_out_str("\x0D\x0A\x00");
713
 
714
//   debug_out_hex(fmt);
715
//   debug_out_str("\x0D\x0A\x00");
716
 
717