/* (c) 2003 Martin Voelkle & Stephane Magnenat */ #include #include #include #include #include Sint16 minsint16 = (1 << (sizeof(Sint16)*8-1)); Sint16 maxsint16 = minsint16 - 1; struct Tracks { int ntracks; int *gains; int *indexes; OggVorbis_File *files; }; int run; #define CLAMP(val, min, max) { if ((val)<(min)) (val)=(min); else if ((val)>(max)) (val)=(max); } void mixaudio(void *tracks, Uint8 *stream, int len) { Tracks *t = (Tracks *)tracks; int nsamples = len >> 1; Sint16 track[nsamples]; Sint16 *mix = (Sint16 *)stream; // init buffer for (int j = 0; j < nsamples; j++) { mix[j] = 0; } for (int i = 0; i < t->ntracks; i++) { // read ogg long rest = len; char *p = (char *)track; while(rest > 0) { long ret = ov_read(&t->files[i], p, rest, 0, 2, 1, &t->indexes[i]); if (ret == 0) // EOF { ov_pcm_seek(&t->files[i], 0); } else if (ret < 0) // stream error { } else { rest -= ret; p += ret; } } // sum sample for (int j = 0; j < nsamples; j++) { mix[j] = minsint16 >? (mix[j] + ((track[j] * t->gains[i])>>8)) ntracks; i++) { SDL_Rect sel = {i*30, 255-t->gains[i], 30, t->gains[i]}; SDL_FillRect(s, &sel, SDL_MapRGB(s->format, 255, 20, 20)); SDL_Rect black = {i*30, 0, 30, 255-t->gains[i]}; SDL_FillRect(s, &black, SDL_MapRGB(s->format, 50, 50, 50)); } SDL_Flip(s); } void handle_gain_change(SDL_Event *event, Tracks *t) { int id = event->button.x/30; int gain = 255-event->button.y; CLAMP(id, 0, t->ntracks-1); CLAMP(gain, 0, 255); t->gains[id] = gain; } int main(int argc, char **argv) { if (argc==1) { printf("Usage: %s file.ogg {file.ogg}\n", argv[0]); exit(1); } SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO); Tracks t; t.ntracks = argc - 1; t.gains = new int[t.ntracks]; t.indexes = new int[t.ntracks]; t.files = new OggVorbis_File[t.ntracks]; for (int i = 0; i < t.ntracks; i++) { t.gains[i] = 255/t.ntracks; FILE* file = fopen(argv[i+1], "rb"); if (ov_open(file, &t.files[i], NULL, 0) < 0) { fprintf(stderr, "File does not appear to be an Ogg bitstream.\n"); exit(1); } } SDL_AudioSpec as; // Set 16-bit stereo audio at 44Khz as.freq = 44100; as.format = AUDIO_S16; as.channels = 2; as.samples = 512; as.callback = mixaudio; as.userdata = &t; // Open the audio device and start playing sound! if (SDL_OpenAudio(&as, NULL) < 0) { fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); exit(1); } // Init video SDL_Surface *screen; screen = SDL_SetVideoMode(t.ntracks*30, 256, 32, SDL_HWSURFACE|SDL_DOUBLEBUF); if (screen == NULL) { fprintf(stderr, "Unable to set %dx256 video: %s\n", t.ntracks, SDL_GetError()); exit(1); } redisplay(screen, &t); SDL_PauseAudio(0); SDL_Event event; while (SDL_WaitEvent(&event)) { if (event.type == SDL_QUIT) { break; } else if ((event.type == SDL_MOUSEBUTTONDOWN) || ((event.type == SDL_MOUSEMOTION) && (event.motion.state))) { handle_gain_change(&event, &t); redisplay(screen, &t); } } SDL_PauseAudio(1); for(int i=0; i