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