player/audioplayer.c
changeset 0 06dd3b8d90ad
equal deleted inserted replaced
-1:000000000000 0:06dd3b8d90ad
       
     1 /**
       
     2  *  $Id: audioplayer.c 53 2008-01-10 00:19:41Z mbroeker $
       
     3  * $URL: http://localhost/svn/c/VirtualReader/trunk/player/audioplayer.c $
       
     4  */
       
     5 
       
     6 #include <audioplayer.h>
       
     7 
       
     8 typedef struct {
       
     9     SDL_AudioSpec spec;         // internal structure
       
    10     Uint8 *sound_buffer;        // malloced pointer from sdl
       
    11     Uint32 sound_pos;           // position
       
    12     Uint32 sound_len;           // length in bytes
       
    13     Uint32 length;              // Length in Milliseconds
       
    14 
       
    15     int opened;                 // bool opened
       
    16     int loaded;                 // bool loaded
       
    17     int verbose;                // verbose messages
       
    18     int timeout;                // timeout
       
    19     int timer;                  // bool timer
       
    20 } AudioDevice;
       
    21 
       
    22 AudioDevice AD;
       
    23 
       
    24 int audio_init ()
       
    25 {
       
    26     // initialize SDL for audio output
       
    27     if (SDL_Init (SDL_INIT_AUDIO) < 0) {
       
    28         fprintf (stderr, "audio_init: Cannot initialize SDL-Subsystem\n");
       
    29         return -1;
       
    30     }
       
    31 
       
    32     AD.sound_buffer = 0;
       
    33     AD.sound_pos = 0;
       
    34     AD.sound_len = 0;
       
    35 
       
    36     AD.opened = 0;
       
    37     AD.loaded = 0;
       
    38     AD.verbose = 0;
       
    39 
       
    40     AD.timeout = 0;
       
    41     AD.timer = 0;
       
    42 
       
    43     return 0;
       
    44 }
       
    45 
       
    46 void audio_shutdown ()
       
    47 {
       
    48     // quit sdl
       
    49     SDL_AudioQuit ();
       
    50     SDL_Quit ();
       
    51 }
       
    52 
       
    53 static void Callback (void *userdata, Uint8 * stream, int len)
       
    54 {
       
    55     Uint8 *waveptr = NULL;
       
    56 
       
    57     /*
       
    58      *     loaded = 0 Segmentation fault
       
    59      *        len = 0 nothing to play
       
    60      */
       
    61     if (!(AD.loaded && len))
       
    62         return;
       
    63 
       
    64     waveptr = AD.sound_buffer + AD.sound_pos;
       
    65     SDL_MixAudio (stream, waveptr, len, SDL_MIX_MAXVOLUME);
       
    66     AD.sound_pos += len;        // bereits gespielt
       
    67 
       
    68     if (audioplayer_gettime () > (AD.length - AD.timeout)) {
       
    69         AD.sound_pos = AD.length;
       
    70         AD.sound_len = 0;
       
    71         AD.timer = 0;
       
    72     }
       
    73 }
       
    74 
       
    75 Uint32 audioplayer_getsoundlen ()
       
    76 {
       
    77     return AD.sound_len;
       
    78 }
       
    79 
       
    80 void audioplayer_media_info (char *fname)
       
    81 {
       
    82     AD.length = audioplayer_getwavelength (fname);
       
    83 
       
    84     printf ("Playing %s: %d Hz, %d Bit Audio, %d Channel(s), %3.2d ms\n",
       
    85             fname, AD.spec.freq, audioplayer_getbitrate (), AD.spec.channels, AD.length);
       
    86 }
       
    87 
       
    88 int audioplayer_getbitrate ()
       
    89 {
       
    90     int bitrate = 0;
       
    91 
       
    92     switch (AD.spec.format) {
       
    93     case AUDIO_U8:
       
    94     case AUDIO_S8:
       
    95         bitrate = 8;
       
    96         break;
       
    97     case AUDIO_S16LSB:
       
    98     case AUDIO_S16MSB:
       
    99     case AUDIO_U16LSB:
       
   100     case AUDIO_U16MSB:
       
   101         bitrate = 16;
       
   102         break;
       
   103     }
       
   104 
       
   105     return bitrate;
       
   106 }
       
   107 
       
   108 Uint32 audioplayer_getwavelength (char *fname)
       
   109 {
       
   110     struct stat info;
       
   111     Uint32 value = 0;
       
   112 
       
   113     if (fname == NULL)
       
   114         return AD.length;
       
   115 
       
   116     if (stat (fname, &info) == 0)
       
   117         /*
       
   118          * the value is really big, so be carefull
       
   119          * changes in the order result in different values
       
   120          * the storage type isn`t well choosen...
       
   121          */
       
   122         value = ((info.st_size) / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0);
       
   123 
       
   124     return (value);
       
   125 }
       
   126 
       
   127 Uint32 audioplayer_getposition ()
       
   128 {
       
   129     return AD.sound_pos;
       
   130 }
       
   131 
       
   132 Uint32 audioplayer_gettime ()
       
   133 {
       
   134     Uint32 ret;
       
   135 
       
   136     ret = AD.sound_pos / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0;
       
   137 
       
   138     return ret;
       
   139 }
       
   140 
       
   141 void audioplayer_settime (long tm)
       
   142 {
       
   143     AD.sound_pos = tm / 1000.0 * (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0));
       
   144 
       
   145     /*
       
   146      * Eine Adresse ...
       
   147      */
       
   148     while ((AD.sound_pos % 2) != 0)
       
   149         AD.sound_pos++;
       
   150 
       
   151     if (AD.verbose)
       
   152         printf ("\e[31m[ATTENTION]\e[37m [#%d/#%d] = %d ms\n", AD.sound_pos, AD.sound_len, audioplayer_gettime ());
       
   153 }
       
   154 
       
   155 void audioplayer_stop ()
       
   156 {
       
   157     /*
       
   158      * stops the callback function
       
   159      */
       
   160     SDL_PauseAudio (1);
       
   161     AD.spec.callback = NULL;
       
   162 
       
   163     if (AD.loaded == 1)
       
   164         SDL_FreeWAV (AD.sound_buffer);
       
   165 
       
   166     AD.loaded = 0;
       
   167     AD.timer = 0;
       
   168 }
       
   169 
       
   170 void audioplayer_delay (Uint32 milliseconds)
       
   171 {
       
   172     struct timespec tm;
       
   173 
       
   174     tm.tv_sec = 0;
       
   175     tm.tv_nsec = milliseconds * 1000;
       
   176 
       
   177     while (AD.timer)
       
   178         nanosleep (&tm, NULL);
       
   179 }
       
   180 
       
   181 void audioplayer_setverbose (int verbose)
       
   182 {
       
   183     AD.verbose = verbose;
       
   184 }
       
   185 
       
   186 int audioplayer (char *fname, Uint32 timeout)
       
   187 {
       
   188     if (SDL_LoadWAV (fname, &AD.spec, &AD.sound_buffer, &AD.sound_len) == NULL) {
       
   189         printf ("SDL: %s\n", SDL_GetError ());
       
   190         return -1;
       
   191     }
       
   192 
       
   193     AD.loaded = 1;
       
   194 
       
   195     if (!AD.opened) {
       
   196         AD.spec.callback = Callback;
       
   197         if (SDL_OpenAudio (&AD.spec, NULL) < 0) {
       
   198             fprintf (stderr, "Cannot open audio device: %s\n", SDL_GetError ());
       
   199             return -1;
       
   200         }
       
   201         AD.opened = 1;
       
   202     }
       
   203 
       
   204     /*
       
   205      * calls implicitly getwavelength
       
   206      */
       
   207     audioplayer_media_info (fname);
       
   208 
       
   209     AD.sound_pos = 0;
       
   210 
       
   211     /*
       
   212      * starts playback via Callback function
       
   213      */
       
   214     SDL_PauseAudio (0);
       
   215 
       
   216     /*
       
   217      * initializes the timeout mechanism
       
   218      */
       
   219     AD.timer = 1;
       
   220     AD.timeout = timeout;
       
   221 
       
   222     /*
       
   223      * controlled delay
       
   224      */
       
   225     audioplayer_delay (timeout);
       
   226 
       
   227     return 0;
       
   228 }