Subversion Repositories Kolibri OS

Rev

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