00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include <time.h>
00005 #include <sys/time.h>
00006 #include <math.h>
00007 #include <signal.h>
00008 #include <memory.h>
00009 #include <SDL.h>
00010
00011 #include <vorbis/vorbisfile.h>
00012
00013 struct music_file {
00014 struct music_file *next;
00015 char *name;
00016 char *buf;
00017 int size;
00018 };
00019 struct music_file *music_files;
00020
00021 struct music_file *
00022 get_music_file (char *name)
00023 {
00024 struct music_file *mp;
00025 FILE *inf;
00026 int togo, offset;
00027 OggVorbis_File vf;
00028 int ret;
00029 int bs;
00030 char fullname[1000];
00031 int chop;
00032
00033 for (mp = music_files; mp; mp = mp->next) {
00034 if (xstrcasecmp (name, mp->name) == 0)
00035 return (mp);
00036 }
00037
00038 sprintf (fullname, "/home/pace/ogg/%s.ogg", name);
00039
00040 fprintf (stderr, "opening music file `%s'", fullname);
00041
00042 if ((inf = fopen(fullname, "rb")) == NULL) {
00043 fprintf(stderr, "can't open music file `%s'", fullname);
00044 return NULL;
00045 }
00046
00047 if ((mp = calloc (1, sizeof *mp)) == NULL) {
00048 fprintf (stderr, "out of memory\n");
00049 exit (1);
00050 }
00051
00052 if ((mp->name = strdup (name)) == NULL) {
00053 fprintf (stderr, "out of memory\n");
00054 exit (1);
00055 }
00056
00057 mp->next = music_files;
00058 music_files = mp;
00059
00060 if (ov_open (inf, &vf, NULL, 0) < 0) {
00061 fprintf(stderr, "ERROR: Failed to open input as vorbis\n");
00062 goto bad;
00063 }
00064
00065 if (ov_info(&vf, 0)->channels != 1) {
00066 fprintf (stderr, "ERROR: ogg file must be mono\n");
00067 goto bad;
00068 }
00069
00070 mp->size = ov_pcm_total(&vf, 0);
00071
00072 if ((mp->buf = calloc (1, mp->size)) == NULL) {
00073 fprintf (stderr, "out of memory\n");
00074 exit (1);
00075 }
00076
00077 togo = mp->size;
00078 offset = 0;
00079
00080 while (togo > 0) {
00081 if ((ret = ov_read (&vf, mp->buf + offset,
00082 togo, 0, 1, 0, &bs)) < 0)
00083 break;
00084
00085 offset += ret;
00086 togo -= ret;
00087 }
00088
00089 ov_clear(&vf);
00090
00091 chop = 2 * 11025;
00092 if (mp->size > chop)
00093 mp->size -= chop;
00094
00095 return (mp);
00096 bad:
00097 fclose (inf);
00098 return (mp);
00099 }
00100
00101 SDL_Surface *sur;
00102
00103
00104 double
00105 get_time (void)
00106 {
00107 struct timeval tv;
00108 gettimeofday (&tv, NULL);
00109 return (tv.tv_sec + tv.tv_usec / 1e6);
00110 }
00111
00112 void
00113 intr (int sig)
00114 {
00115 SDL_Quit ();
00116 exit (0);
00117 }
00118
00119 int have_audio;
00120
00121 SDL_AudioSpec audio_desired, audio_obtained;
00122
00123 struct audio_chunk {
00124 struct audio_chunk *next;
00125 unsigned char *data;
00126 int size;
00127 int loop;
00128 };
00129
00130 struct audio_chunk *cur_chunk, **cur_chunk_tailp = &cur_chunk;
00131 int cur_offset;
00132
00133 void
00134 audio_callback (void *userdata, Uint8 *stream, int len)
00135 {
00136 int togo, thistime;
00137
00138 togo = len;
00139
00140 while (togo && cur_chunk) {
00141 thistime = cur_chunk->size - cur_offset;
00142 if (thistime > togo)
00143 thistime = togo;
00144 memcpy (stream, cur_chunk->data + cur_offset, thistime);
00145
00146 stream += thistime;
00147 togo -= thistime;
00148 cur_offset += thistime;
00149
00150 if (cur_offset >= cur_chunk->size) {
00151 if (cur_chunk->loop == 0) {
00152 if ((cur_chunk = cur_chunk->next) == NULL)
00153 cur_chunk_tailp = &cur_chunk;
00154 }
00155 cur_offset = 0;
00156 }
00157 }
00158
00159 memset (stream, audio_obtained.silence, togo);
00160 }
00161
00162 void
00163 play (struct audio_chunk *new_chunk)
00164 {
00165 if (have_audio == 0)
00166 return;
00167 SDL_LockAudio ();
00168 *cur_chunk_tailp = new_chunk;
00169 SDL_UnlockAudio ();
00170 }
00171
00172 void
00173 test_news (void)
00174 {
00175 struct audio_chunk *cp;
00176 FILE *f;
00177
00178 cp = calloc (1, sizeof *cp);
00179 cp->data = malloc (1000 * 1000);
00180
00181 if ((f = fopen ("/l/baris/gamedat/unews.cdr", "rb")) == NULL) {
00182 fprintf (stderr, "can't open unews.cdr\n");
00183 exit (1);
00184 }
00185
00186 cp->size = fread (cp->data, 1, 1000 * 1000, f);
00187
00188 fclose (f);
00189
00190 play (cp);
00191 }
00192
00193 void
00194 test_music (void)
00195 {
00196 struct music_file *mp;
00197 struct audio_chunk *cp;
00198
00199 if ((mp = get_music_file ("SOVTYP")) == NULL) {
00200 fprintf (stderr, "can't find music file\n");
00201 exit (1);
00202 }
00203
00204 if (mp->buf == NULL || mp->size == 0) {
00205 fprintf (stderr, "can't get music\n");
00206 exit (1);
00207 }
00208
00209 cp = calloc (1, sizeof *cp);
00210 cp->data = (void *)mp->buf;
00211 cp->size = mp->size;
00212 cp->loop = 1;
00213 play (cp);
00214 }
00215
00216 int
00217 main ()
00218 {
00219 SDL_Rect r;
00220 SDL_Event ev;
00221
00222 if (SDL_Init (SDL_INIT_VIDEO) < 0) {
00223 fprintf (stderr, "SDL_Init error\n");
00224 exit (1);
00225 }
00226
00227
00228 if (SDL_InitSubSystem (SDL_INIT_AUDIO < 0)) {
00229 printf ("no audio\n");
00230 } else {
00231 printf ("audio initialized\n");
00232 have_audio = 1;
00233 }
00234
00235 if ((sur = SDL_SetVideoMode (320, 200, 24, SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL) {
00236 fprintf (stderr, "error in SDL_SetVideoMode\n");
00237 exit (1);
00238 }
00239
00240 SDL_EnableUNICODE (1);
00241
00242 audio_desired.freq = 11025;
00243 audio_desired.format = AUDIO_U8;
00244 audio_desired.channels = 1;
00245 audio_desired.samples = 8192;
00246 audio_desired.callback = audio_callback;
00247
00248 if (SDL_OpenAudio (&audio_desired, &audio_obtained) < 0) {
00249 fprintf (stderr, "error in SDL_OpenAudio\n");
00250 exit (1);
00251 }
00252
00253 test_music ();
00254 SDL_PauseAudio (0);
00255
00256 while (1) {
00257 while (SDL_PollEvent (&ev)) {
00258 switch (ev.type) {
00259 case SDL_QUIT:
00260 exit (0);
00261 break;
00262 case SDL_KEYDOWN:
00263 printf ("got key %d\n", ev.key.keysym.unicode);
00264 break;
00265
00266
00267 case SDL_KEYUP:
00268 case SDL_ACTIVEEVENT:
00269 case SDL_MOUSEMOTION:
00270 break;
00271 default:
00272 printf ("got uknown event %d\n", ev.type);
00273 break;
00274 }
00275 }
00276
00277 r.x = 0; r.y = 0; r.w = 320; r.h = 200;
00278 SDL_FillRect (sur, &r, 0);
00279
00280 r.x = 160 + 120 * cos (get_time () * .5 * M_PI);
00281 r.y = 100;
00282 r.w = 20;
00283 r.h = 20;
00284 SDL_FillRect (sur, &r, 0xff0000);
00285
00286 SDL_Flip (sur);
00287
00288 usleep (33 * 1000);
00289
00290 }
00291
00292 return (0);
00293 }
00294