Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <stdint.h>
  3. #include <libavcodec/avcodec.h>
  4. #include <libavformat/avformat.h>
  5. #include <libswscale/swscale.h>
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "sound.h"
  10. #include "fplay.h"
  11.  
  12.  
  13. astream_t astream;
  14.  
  15. static SNDBUF hBuff;
  16.  
  17. extern volatile uint32_t status;
  18.  
  19. void audio_thread(void *param);
  20.  
  21. void spinlock_lock(volatile uint32_t *val)
  22. {
  23.     uint32_t tmp;
  24.  
  25.     __asm__ __volatile__ (
  26. "0:\n\t"
  27.     "mov %0, %1\n\t"
  28.     "testl %1, %1\n\t"
  29.     "jz 1f\n\t"
  30.  
  31.     "movl $68, %%eax\n\t"
  32.     "movl $1,  %%ebx\n\t"
  33.     "int  $0x40\n\t"
  34.     "jmp 0b\n\t"
  35. "1:\n\t"
  36.     "incl %1\n\t"
  37.     "xchgl %0, %1\n\t"
  38.     "testl %1, %1\n\t"
  39.         "jnz 0b\n"
  40.     : "+m" (*val), "=&r"(tmp)
  41.     ::"eax","ebx" );
  42. }
  43.  
  44. static int snd_format;
  45. int sample_rate;
  46.  
  47. int init_audio(int format)
  48. {
  49.     int    err;
  50.     int    version =-1;
  51.     char  *errstr;
  52.  
  53.     if((err = InitSound(&version)) !=0 )
  54.     {
  55.         errstr = "Sound service not installed\n\r";
  56.         goto exit_whith_error;
  57.     }
  58.     printf("sound version 0x%x\n", version);
  59.  
  60.     if( (SOUND_VERSION>(version&0xFFFF)) ||
  61.         (SOUND_VERSION<(version >> 16)))
  62.     {
  63.         errstr = "Sound service version mismatch\n\r";
  64.         goto exit_whith_error;
  65.     }
  66.  
  67.     snd_format = format;
  68.  
  69.     asm volatile ( "xchgw %bx, %bx");
  70.  
  71.     create_thread(audio_thread, 0, 163840);
  72.  
  73.     return 1;
  74.  
  75. exit_whith_error:
  76.  
  77.     printf(errstr);
  78.     return 0;
  79. };
  80.  
  81. static uint64_t samples_lost;
  82. static double  audio_delta;
  83.  
  84. double get_master_clock()
  85. {
  86.     double tstamp;
  87.  
  88.     GetTimeStamp(hBuff, &tstamp);
  89.     return tstamp - audio_delta;
  90. };
  91.  
  92.  
  93. void audio_thread(void *param)
  94. {
  95.     SND_EVENT evnt;
  96.     int       buffsize;
  97.     int      samples;
  98.     int       err;
  99.     char     *errstr;
  100.  
  101.  
  102.     if((err = CreateBuffer(snd_format|PCM_RING,0, &hBuff)) != 0)
  103.     {
  104.         errstr = "Cannot create sound buffer\n\r";
  105.         goto exit_whith_error;
  106.     };
  107.  
  108.     SetVolume(hBuff,-1000,-1000);
  109.  
  110.     if((err = GetBufferSize(hBuff, &buffsize)) != 0)
  111.     {
  112.         errstr = "Cannot get buffer size\n\r";
  113.         goto exit_whith_error;
  114.     };
  115.  
  116.     buffsize = buffsize/2;
  117.  
  118.     samples = buffsize/4;
  119.  
  120.     while( (astream.count < buffsize*2) &&
  121.                (status != 0) )
  122.         yield();
  123.  
  124.     spinlock_lock(&astream.lock);
  125.     {
  126.         SetBuffer(hBuff, astream.buffer, 0, buffsize);
  127.         astream.count -= buffsize;
  128.         if(astream.count)
  129.             memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  130.         spinlock_unlock(&astream.lock);
  131.     };
  132.  
  133.     if((err = PlayBuffer(hBuff, 0)) !=0 )
  134.     {
  135.         errstr = "Cannot play buffer\n\r";
  136.         goto exit_whith_error;
  137.     };
  138.  
  139.  
  140. #ifdef BLACK_MAGIC_SOUND
  141.  
  142.     while( status != 0)
  143.     {
  144.         uint32_t  offset;
  145.  
  146.         GetNotify(&evnt);
  147.  
  148.         if(evnt.code != 0xFF000001)
  149.         {
  150.             printf("invalid event code %d\n\r", evnt.code);
  151.             continue;
  152.         }
  153.  
  154.         if(evnt.stream != hBuff)
  155.         {
  156.             printf("invalid stream %x hBuff= %x\n\r",
  157.                     evnt.stream, hBuff);
  158.             continue;
  159.         }
  160.  
  161.         GetTimeStamp(hBuff, &audio_delta);
  162.         samples_lost = audio_delta*sample_rate/1000;
  163.  
  164.         offset = evnt.offset;
  165.  
  166.         spinlock_lock(&astream.lock);
  167.         {
  168.             SetBuffer(hBuff, astream.buffer, offset, buffsize);
  169.             astream.count -= buffsize;
  170.             if(astream.count)
  171.                 memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  172.             spinlock_unlock(&astream.lock);
  173.         };
  174.         break;
  175.     };
  176. #endif
  177.  
  178.     printf("initial audio delta %f\n", audio_delta);
  179.  
  180.     while( status != 0)
  181.     {
  182.         uint32_t  offset;
  183.         double    event_stamp, wait_stamp;
  184.         int       too_late = 0;
  185.  
  186.         GetNotify(&evnt);
  187.  
  188.         if(evnt.code != 0xFF000001)
  189.         {
  190.             printf("invalid event code %d\n\r", evnt.code);
  191.             continue;
  192.         }
  193.  
  194.         if(evnt.stream != hBuff)
  195.         {
  196.             printf("invalid stream %x hBuff= %x\n\r",
  197.                     evnt.stream, hBuff);
  198.             continue;
  199.         };
  200.  
  201.         GetTimeStamp(hBuff, &event_stamp);
  202.  
  203.         offset = evnt.offset;
  204.  
  205.         while( (astream.count < buffsize) &&
  206.                (status != 0) )
  207.         {
  208.             yield();
  209.             GetTimeStamp(hBuff, &wait_stamp);
  210.             if( (wait_stamp - event_stamp) >
  211.                  samples*1500/sample_rate )
  212.             {
  213.                 samples_lost+= samples;
  214.                 audio_delta = (double)samples_lost*1000/sample_rate;
  215. //                printf("audio delta %f\n", audio_delta);
  216.                 too_late = 1;
  217.                 break;
  218.             }
  219.         };
  220.  
  221.         if((too_late == 1) || (status == 0))
  222.             continue;
  223.  
  224.         spinlock_lock(&astream.lock);
  225.         SetBuffer(hBuff, astream.buffer, offset, buffsize);
  226.         astream.count -= buffsize;
  227.         if(astream.count)
  228.             memcpy(astream.buffer, astream.buffer+buffsize, astream.count);
  229.         spinlock_unlock(&astream.lock);
  230.     }
  231.  
  232.     return;
  233.  
  234. exit_whith_error:
  235.  
  236.     printf(errstr);
  237.     return ;
  238.  
  239. };
  240.  
  241.