int main(int argc, char** argv) { // zak³ada siê, ¿e ramka zawiera próbkê, w której // jest d¼wiêk beat-u i cisza do nastêpnego beatu // // // ramka //char *pFrame; // licznik int i; // goc_termInit(); printf(GOC_STRING_WHITE); // Procedury inicjuj±ce GOC_DEBUG("Initializing libao"); ao_initialize(); GOC_DEBUG("Initializing libao Device"); aodriverid = ao_default_driver_id(); if ( aodriverid == -1 ) return -1; openOutputDevice(); params = allocParameters(); if ( argc > 1 ) { if ( interpretArgs(argc, argv, params) < 0 ) endProgram(-1); } GOC_DEBUG("Allocating buffer"); generateBeat(params, BEAT_BASE); generateBeat(params, BEAT_ACCENT); generateBeat(params, BEAT_INTER); generateBeat(params, BEAT_QUIET); // pFrame = malloc(nFrame); // memset(pFrame, 0, nFrame); GOC_BINFO("Tempo: %d Rate: %d Channels: %d Bits: %d", params->tempo, SAMPLE_RATE, SAMPLE_CHANNELS, SAMPLE_BITS); // GOC_BDEBUG("Allocated %d at 0x%X", nFrame, (unsigned int)pFrame); if ( params->flags & FLAG_PRINTCOUNT ) { goc_clearscreen(); goc_gotoxy(1,1); } printf("Playing ... \n"); if ( params->pattern ) printf("Use pattern: %s\n", params->pattern); fflush(stdout); { // to nie do koñca jest liczba ramek - to jest liczba // podstawowych beatów jakie maj± zostaæ zagrane - nie // s± liczone beat-y po¶rednie int nFrames; int imeasure = 0; int iinter; int patternPosition = 0; int patternLen = 0; char *prevString = goc_stringCopy(NULL, ""); char playedPattern = '.'; if ( params->pattern ) { patternLen = strlen(params->pattern); } if ( params->tacts ) // na podstawie liczby podanych taktów nFrames = params->tacts * params->measure; else // na podstawie podanego czasu nFrames = params->tempo * params->pdur / 60; NEXTPATTERN(); // goc_saveXY(); for (i=0; i<nFrames; i++) { if ( imeasure ) { if ( params->flags & FLAG_PRINTCOUNT ) { goc_gotoxy(1, 5); printf("%s%s%s%d%s", GOC_STRING_YELLOW, prevString, GOC_STRING_BWHITE, imeasure + 1, GOC_STRING_YELLOW); prevString = goc_stringAddInt(prevString, imeasure+1); prevString = goc_stringAdd(prevString, " .. "); fflush(stdout); } if ( playedPattern == '.' ) ao_play(aodev, params->pBeat[BEAT_BASE].pFrame, params->pBeat[BEAT_BASE].nFrame); else ao_play(aodev, params->pBeat[BEAT_QUIET].pFrame, params->pBeat[BEAT_QUIET].nFrame); NEXTPATTERN(); } else { if ( params->flags & FLAG_PRINTCOUNT ) { goc_gotoxy(1, 5); printf("%s%s", GOC_STRING_YELLOW, prevString); goc_gotoxy(1, 5); printf("%s%d%s", GOC_STRING_BWHITE, imeasure + 1, GOC_STRING_YELLOW); prevString = goc_stringFree(prevString); prevString = goc_stringAddInt(prevString, imeasure+1); prevString = goc_stringAdd(prevString, " .. "); fflush(stdout); } if ( playedPattern == '.' ) ao_play(aodev, params->pBeat[BEAT_ACCENT].pFrame, params->pBeat[BEAT_ACCENT].nFrame); else ao_play(aodev, params->pBeat[BEAT_QUIET].pFrame, params->pBeat[BEAT_QUIET].nFrame); NEXTPATTERN(); } if ( (iinter = params->inter) ) { while ( iinter-- ) { if ( params->flags & FLAG_PRINTCOUNT ) { goc_gotoxy(1, 5); printf("%s%s%si%s", GOC_STRING_YELLOW, prevString, GOC_STRING_WHITE, GOC_STRING_YELLOW); prevString = goc_stringAdd(prevString, "i .. "); fflush(stdout); } if ( playedPattern == '.' ) ao_play(aodev, params->pBeat[BEAT_INTER].pFrame, params->pBeat[BEAT_INTER].nFrame); else ao_play(aodev, params->pBeat[BEAT_QUIET].pFrame, params->pBeat[BEAT_QUIET].nFrame); NEXTPATTERN(); } } imeasure++; imeasure %= params->measure; } if ( params->flags & FLAG_PRINTCOUNT ) { goc_gotoxy(1, 5); printf("%s%s", GOC_STRING_YELLOW, prevString); } prevString = goc_stringFree(prevString); } printf("%s\nFinish\n", GOC_STRING_WHITE); if ( params->tacts ) { GOC_BINFO("Played %d frames in %d tacts", i, params->tacts); } else { GOC_BINFO("Played %d frames in %d seconds", i, params->pdur); } endProgram(0); return 0; }
static int stream_loop(mpg123_handle *mh, int socket) { ao_device *dev; ao_sample_format format; size_t bytes_decoded; int status; unsigned char out_buffer[OUT_BUF_SIZE]; int channels; int encoding; long rate; /* listen to socket */ if (mpg123_open_fd(mh, socket) == MPG123_ERR) { fprintf(stderr, "%s\n", mpg123_strerror(mh)); return 1; } status = MPG123_OK; /* set some standard format */ memset(&format, 0, sizeof(ao_sample_format)); format.rate = 44100; format.channels = 2; format.byte_format = AO_FMT_LITTLE; format.bits = 16; dev = ao_open_live(ao_default_driver_id(), &format, NULL); if (!dev) { fprintf(stderr, "ao_open_live failed()"); return 1; } do { if (g_paused) { fprintf(stderr, "paused\n"); sleep(1); continue; } status = mpg123_read(mh, out_buffer, OUT_BUF_SIZE, &bytes_decoded); if (status != 0) { fprintf(stderr, "status [%d] - %s\n", status, mpg123_plain_strerror(status)); } if (status == MPG123_ERR || status == MPG123_DONE) { break; } else { if (status == MPG123_NEW_FORMAT) { status = mpg123_getformat(mh, &rate, &channels, &encoding); fprintf(stderr, "new format:\n\trate: %ld\n\tchannels:%d\n\tencoding: %d\n", rate, channels, encoding); format.rate = rate; format.channels = channels; format.byte_format = AO_FMT_LITTLE; format.bits = mpg123_encsize(encoding) * 8; /* close and reopen again for new format */ ao_close(dev); dev = ao_open_live(ao_default_driver_id(), &format, NULL); if (!dev) { fprintf(stderr, "ao_open_live failed\n"); break; } } if (dev) { ao_play(dev, (char*)out_buffer, bytes_decoded); } } } while (g_go_on && !g_stop); if (dev) { fprintf(stderr, "stderr close ao device\n"); ao_close(dev); } return status; }
UINT8 StartStream(UINT8 DeviceID) { UINT32 RetVal; #ifdef USE_LIBAO ao_sample_format ao_fmt; #else #ifdef WIN32 UINT16 Cnt; HANDLE WaveOutThreadHandle; DWORD WaveOutThreadID; //char TestStr[0x80]; #elif defined(__NetBSD__) struct audio_info AudioInfo; #else UINT32 ArgVal; #endif #endif // ! USE_LIBAO if (WaveOutOpen) return 0xD0; // Thread is already active // Init Audio WaveFmt.wFormatTag = WAVE_FORMAT_PCM; WaveFmt.nChannels = 2; WaveFmt.nSamplesPerSec = SampleRate; WaveFmt.wBitsPerSample = 16; WaveFmt.nBlockAlign = WaveFmt.wBitsPerSample * WaveFmt.nChannels / 8; WaveFmt.nAvgBytesPerSec = WaveFmt.nSamplesPerSec * WaveFmt.nBlockAlign; WaveFmt.cbSize = 0; if (DeviceID == 0xFF) return 0x00; #if defined(WIN32) || defined(USE_LIBAO) BUFFERSIZE = SampleRate / 100 * SAMPLESIZE; if (BUFFERSIZE > BUFSIZE_MAX) BUFFERSIZE = BUFSIZE_MAX; #else BUFFERSIZE = 1 << BUFSIZELD; #endif SMPL_P_BUFFER = BUFFERSIZE / SAMPLESIZE; if (AUDIOBUFFERU > AUDIOBUFFERS) AUDIOBUFFERU = AUDIOBUFFERS; PauseThread = true; ThreadPauseConfrm = false; CloseThread = false; StreamPause = false; #ifndef USE_LIBAO #ifdef WIN32 ThreadPauseEnable = true; WaveOutThreadHandle = CreateThread(NULL, 0x00, &WaveOutThread, NULL, 0x00, &WaveOutThreadID); if(WaveOutThreadHandle == NULL) return 0xC8; // CreateThread failed CloseHandle(WaveOutThreadHandle); RetVal = waveOutOpen(&hWaveOut, ((UINT)DeviceID - 1), &WaveFmt, 0x00, 0x00, CALLBACK_NULL); if(RetVal != MMSYSERR_NOERROR) #else ThreadPauseEnable = false; #ifdef __NetBSD__ hWaveOut = open("/dev/audio", O_WRONLY); #else hWaveOut = open("/dev/dsp", O_WRONLY); #endif if (hWaveOut < 0) #endif #else // ifdef USE_LIBAO ao_initialize(); ThreadPauseEnable = false; ao_fmt.bits = WaveFmt.wBitsPerSample; ao_fmt.rate = WaveFmt.nSamplesPerSec; ao_fmt.channels = WaveFmt.nChannels; ao_fmt.byte_format = AO_FMT_NATIVE; ao_fmt.matrix = NULL; dev_ao = ao_open_live(ao_default_driver_id(), &ao_fmt, NULL); if (dev_ao == NULL) #endif { CloseThread = true; return 0xC0; // waveOutOpen failed } WaveOutOpen = true; //sprintf(TestStr, "Buffer 0,0:\t%p\nBuffer 0,1:\t%p\nBuffer 1,0:\t%p\nBuffer 1,1:\t%p\n", // &BufferOut[0][0], &BufferOut[0][1], &BufferOut[1][0], &BufferOut[1][1]); //AfxMessageBox(TestStr); #ifndef USE_LIBAO #ifdef WIN32 for (Cnt = 0x00; Cnt < AUDIOBUFFERU; Cnt ++) { WaveHdrOut[Cnt].lpData = BufferOut[Cnt]; // &BufferOut[Cnt][0x00]; WaveHdrOut[Cnt].dwBufferLength = BUFFERSIZE; WaveHdrOut[Cnt].dwBytesRecorded = 0x00; WaveHdrOut[Cnt].dwUser = 0x00; WaveHdrOut[Cnt].dwFlags = 0x00; WaveHdrOut[Cnt].dwLoops = 0x00; WaveHdrOut[Cnt].lpNext = NULL; WaveHdrOut[Cnt].reserved = 0x00; RetVal = waveOutPrepareHeader(hWaveOut, &WaveHdrOut[Cnt], sizeof(WAVEHDR)); WaveHdrOut[Cnt].dwFlags |= WHDR_DONE; } #elif defined(__NetBSD__) AUDIO_INITINFO(&AudioInfo); AudioInfo.mode = AUMODE_PLAY; AudioInfo.play.sample_rate = WaveFmt.nSamplesPerSec; AudioInfo.play.channels = WaveFmt.nChannels; AudioInfo.play.precision = WaveFmt.wBitsPerSample; AudioInfo.play.encoding = AUDIO_ENCODING_SLINEAR; RetVal = ioctl(hWaveOut, AUDIO_SETINFO, &AudioInfo); if (RetVal) printf("Error setting audio information!\n"); #else ArgVal = (AUDIOBUFFERU << 16) | BUFSIZELD; RetVal = ioctl(hWaveOut, SNDCTL_DSP_SETFRAGMENT, &ArgVal); if (RetVal) printf("Error setting Fragment Size!\n"); ArgVal = AFMT_S16_NE; RetVal = ioctl(hWaveOut, SNDCTL_DSP_SETFMT, &ArgVal); if (RetVal) printf("Error setting Format!\n"); ArgVal = WaveFmt.nChannels; RetVal = ioctl(hWaveOut, SNDCTL_DSP_CHANNELS, &ArgVal); if (RetVal) printf("Error setting Channels!\n"); ArgVal = WaveFmt.nSamplesPerSec; RetVal = ioctl(hWaveOut, SNDCTL_DSP_SPEED, &ArgVal); if (RetVal) printf("Error setting Sample Rate!\n"); #endif #endif // USE_LIBAO if (SoundLog) SaveFile(0x00000000, NULL); PauseThread = false; return 0x00; }
static int init(int argc, char **argv) { const char *str; int value; ao_initialize(); int driver = ao_default_driver_id(); ao_option *ao_opts = NULL; config.audio_backend_buffer_desired_length = 44100; // one second. config.audio_backend_latency_offset = 0; // get settings from settings file first, allow them to be overridden by command line options if (config.cfg != NULL) { /* Get the desired buffer size setting. */ if (config_lookup_int(config.cfg, "ao.audio_backend_buffer_desired_length", &value)) { if ((value < 0) || (value > 66150)) die("Invalid a0 audio backend buffer desired length \"%d\". It should be between 0 and " "66150, default is 44100", value); else { config.audio_backend_buffer_desired_length = value; } } /* Get the latency offset. */ if (config_lookup_int(config.cfg, "ao.audio_backend_latency_offset", &value)) { if ((value < -66150) || (value > 66150)) die("Invalid ao audio backend buffer latency offset \"%d\". It should be between -66150 and +66150, default is 0", value); else config.audio_backend_latency_offset = value; } } optind = 1; // optind=0 is equivalent to optind=1 plus special behaviour argv--; // so we shift the arguments to satisfy getopt() argc++; // some platforms apparently require optreset = 1; - which? int opt; char *mid; while ((opt = getopt(argc, argv, "d:i:n:o:")) > 0) { switch (opt) { case 'd': driver = ao_driver_id(optarg); if (driver < 0) die("could not find ao driver %s", optarg); break; case 'i': ao_append_option(&ao_opts, "id", optarg); break; case 'n': ao_append_option(&ao_opts, "dev", optarg); // Old libao versions (for example, 0.8.8) only support // "dsp" instead of "dev". ao_append_option(&ao_opts, "dsp", optarg); break; case 'o': mid = strchr(optarg, '='); if (!mid) die("Expected an = in audio option %s", optarg); *mid = 0; ao_append_option(&ao_opts, optarg, mid + 1); break; default: help(); die("Invalid audio option -%c specified", opt); } } if (optind < argc) die("Invalid audio argument: %s", argv[optind]); ao_sample_format fmt; memset(&fmt, 0, sizeof(fmt)); fmt.bits = 16; fmt.rate = 44100; fmt.channels = 2; fmt.byte_format = AO_FMT_NATIVE; dev = ao_open_live(driver, &fmt, ao_opts); return dev ? 0 : 1; }
void VoxPlayer::aoplay(const std::string& path) { m_isplaying = true; ao_device* ad = NULL; mpg123_handle* mh = NULL; unsigned char* buf = NULL; size_t bufsz = 0; size_t done = 0; int driver = ao_default_driver_id(); ao_sample_format asf; int channels = 0; int encoding = 0; long rate = 0; if(!(mh = mpg123_new(NULL, NULL))) { ERROR("mpg123_new() failed"); goto error_success; } bufsz = mpg123_outblock(mh); buf = (unsigned char*)malloc(bufsz * sizeof(unsigned char)); if(mpg123_open(mh, path.c_str()) != MPG123_OK) { ERROR("mpg123_open() failed"); goto error_success; } mpg123_volume(mh, 1.4); if(mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) { ERROR("mpg123_getformat() failed"); goto error_success; } asf.bits = mpg123_encsize(encoding) * 8; // BITS asf.rate = rate; asf.channels = channels; asf.byte_format = AO_FMT_NATIVE; asf.matrix = 0; if(!(ad = ao_open_live(driver, &asf, NULL))) { ERROR("ao_open_live() failed"); goto error_success; } while(!g_main.isExit() && !m_interrupt) { int ret = mpg123_read(mh, buf, bufsz, &done); DEBUG("ret=%d, done=%d", ret, done); if(ret == MPG123_OK || ret == MPG123_DONE || ret == MPG123_NEED_MORE) { if(!ao_play(ad, (char*)buf, done)) { ERROR("ao_play() failed"); break; } if(ret == MPG123_DONE) break; continue; } break; } DEBUG("play done"); error_success: if(buf) { free(buf); buf = NULL; } if(ad) { ao_close(ad); ad = NULL; } if(mh) { mpg123_close(mh); mpg123_delete(mh); mh = NULL; } m_isplaying = false; }
/* mp3 playback callback */ static WaitressCbReturn_t BarPlayerMp3Cb (void *ptr, size_t size, void *stream) { const char *data = ptr; struct audioPlayer *player = stream; size_t i; if (BarPlayerCheckPauseQuit (player) || !BarPlayerBufferFill (player, data, size)) { return WAITRESS_CB_RET_ERR; } /* some "prebuffering" */ if (player->mode < PLAYER_RECV_DATA && player->bufferFilled < BAR_PLAYER_BUFSIZE / 2) { return WAITRESS_CB_RET_OK; } mad_stream_buffer (&player->mp3Stream, player->buffer, player->bufferFilled); player->mp3Stream.error = 0; do { /* channels * max samples, found in mad.h */ signed short int madDecoded[2*1152], *madPtr = madDecoded; if (mad_frame_decode (&player->mp3Frame, &player->mp3Stream) != 0) { if (player->mp3Stream.error != MAD_ERROR_BUFLEN) { BarUiMsg (player->settings, MSG_ERR, "mp3 decoding error: %s\n", mad_stream_errorstr (&player->mp3Stream)); return WAITRESS_CB_RET_ERR; } else { /* rebuffering required => exit loop */ break; } } mad_synth_frame (&player->mp3Synth, &player->mp3Frame); for (i = 0; i < player->mp3Synth.pcm.length; i++) { /* left channel */ *(madPtr++) = applyReplayGain (BarPlayerMadToShort ( player->mp3Synth.pcm.samples[0][i]), player->scale); /* right channel */ *(madPtr++) = applyReplayGain (BarPlayerMadToShort ( player->mp3Synth.pcm.samples[1][i]), player->scale); } if (player->mode < PLAYER_AUDIO_INITIALIZED) { ao_sample_format format; int audioOutDriver; player->channels = player->mp3Synth.pcm.channels; player->samplerate = player->mp3Synth.pcm.samplerate; audioOutDriver = ao_default_driver_id(); memset (&format, 0, sizeof (format)); format.bits = 16; format.channels = player->channels; format.rate = player->samplerate; format.byte_format = AO_FMT_NATIVE; if ((player->audioOutDevice = ao_open_live (audioOutDriver, &format, NULL)) == NULL) { player->aoError = 1; BarUiMsg (player->settings, MSG_ERR, "Cannot open audio device\n"); return WAITRESS_CB_RET_ERR; } /* calc song length using the framerate of the first decoded frame */ player->songDuration = (unsigned long long int) player->waith.request.contentLength / ((unsigned long long int) player->mp3Frame.header.bitrate / (unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR / 8LL); /* must be > PLAYER_SAMPLESIZE_INITIALIZED, otherwise time won't * be visible to user (ugly, but mp3 decoding != aac decoding) */ player->mode = PLAYER_RECV_DATA; } /* samples * length * channels */ ao_play (player->audioOutDevice, (char *) madDecoded, player->mp3Synth.pcm.length * 2 * 2); /* avoid division by 0 */ if (player->mode == PLAYER_RECV_DATA) { /* same calculation as in aac player; don't need to divide by * channels, length is number of samples for _one_ channel */ player->songPlayed += (unsigned long long int) player->mp3Synth.pcm.length * (unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR / (unsigned long long int) player->samplerate; } if (BarPlayerCheckPauseQuit (player)) { return WAITRESS_CB_RET_ERR; } } while (player->mp3Stream.error != MAD_ERROR_BUFLEN); player->bufferRead += player->mp3Stream.next_frame - player->buffer; BarPlayerBufferMove (player); return WAITRESS_CB_RET_OK; }
int sound_lowlevel_init( const char *device, int *freqptr, int *stereoptr ) { ao_option *options = NULL; ao_info *driver_info = NULL; int driver_id = -1; static ao_sample_format format = { .bits = 0 }; /* To prevent recursive errors */ static int sound_lowlevel_init_in_progress = 0; int error; if( sound_lowlevel_init_in_progress ) return 0; sound_lowlevel_init_in_progress = 1; ao_initialize(); error = parse_driver_options( device, &driver_id, &options ); if( error ) { settings_current.sound = 0; sound_lowlevel_init_in_progress = 0; return error; } if( driver_id == -1 ) driver_id = ao_default_driver_id(); if( driver_id == -1 ) { ui_error( UI_ERROR_ERROR, "ao: driver '%s' unknown", device ); settings_current.sound = 0; sound_lowlevel_init_in_progress = 0; return 1; } driver_info = ao_driver_info( driver_id ); if( driver_info->type == AO_TYPE_FILE && format.bits != 0 ) { /* OK. We not want to trunc the file :-) */ ui_error( UI_ERROR_WARNING, "ao: must truncate audio file '%s'", filename ); } format.channels = *stereoptr ? 2 : 1; format.rate = *freqptr; format.bits = settings_current.sound_force_8bit ? 8 : 16; format.byte_format = AO_FMT_LITTLE; sixteenbit = settings_current.sound_force_8bit ? 0 : 1; if( driver_info->type == AO_TYPE_LIVE ) { dev_for_ao = ao_open_live( driver_id, &format, options); } else { if( !filename ) filename = (char *)default_filename; dev_for_ao = ao_open_file( driver_id, filename, 1, &format, options); } if( !dev_for_ao ) { driver_error(); settings_current.sound = 0; sound_lowlevel_init_in_progress = 0; return 1; } ao_free_options( options ); sound_lowlevel_init_in_progress = 0; first_init = 0; return 0; } void sound_lowlevel_end( void ) { if( filename != default_filename ) free( filename ); ao_close(dev_for_ao); ao_shutdown(); } void sound_lowlevel_frame( libspectrum_signed_word *data, int len ) { static signed char buf8[4096]; void *data8 = data; len <<= 1; /* now in bytes */ if( !sixteenbit ) { libspectrum_signed_word *src; signed char *dst; int f; src = data; dst = buf8; len >>= 1; for( f = 0; f < len; f++) *dst++ = ( int )( ( *src++ ) / 256 ); data8 = buf8; } ao_play( dev_for_ao, data8, len ); }
int playfile(FILE *fp) { int default_driver; int frames_read; int count; int toread; int readnow; short *buffer; short *groovy; long filestart; ao_device *device; ao_sample_format format; SNDFILE *sndfile; SF_INFO sf_info; ao_initialize(); default_driver = ao_default_driver_id(); sf_info.format = 0; filestart = ftell(fp); sndfile = sf_open_fd(fileno(fp), SFM_READ, &sf_info, 0); memset(&format, 0, sizeof(ao_sample_format)); format.byte_format = AO_FMT_NATIVE; format.bits = 16; format.rate = sf_info.samplerate; // format.channels = sf_info.channels; format.channels = 2; printf("Channels: %d\n", sf_info.channels); printf("Samplerate: %d\n", sf_info.samplerate); device = ao_open_live(default_driver, &format, NULL); if (device == NULL) { printf("Error opening sound device.\n"); return 1; } buffer = malloc(BUFFSIZE * sf_info.channels * sizeof(short)); groovy = malloc(BUFFSIZE * 2 * sizeof(short)); frames_read = 0; toread = sf_info.frames * sf_info.channels; while (toread > 0) { if (toread < BUFFSIZE * sf_info.channels) count = toread; else count = BUFFSIZE * sf_info.channels; frames_read = sf_read_short(sndfile, buffer, count); if (sf_info.channels == 1) stereoize(groovy, buffer, count * sizeof(short)); else memcpy(groovy, buffer, count * sizeof(short)); ao_play(device, (char *)groovy, frames_read * sizeof(short)); toread = toread - frames_read; } free(buffer); free(groovy); fseek(fp, filestart, SEEK_SET); ao_close(device); sf_close(sndfile); ao_shutdown(); printf("Finished\n"); return 0; }
/* SNDDMA_Init: initialises cycling through a DMA bufffer and returns * information on it */ qboolean SNDDMA_Init(struct sndinfo * s){ int driver_id; ao_sample_format format; ao_option * options = NULL; if(snd_inited) return 1; snd_inited = 0; si = s; ao_initialize(); if((driver_id = ao_driver_id(si->device->string)) == -1){ si->Com_Printf("ao: no driver %s found, trying default\n", si->device->string); if((driver_id = ao_default_driver_id()) == -1){ Com_Printf("ao: no default driver found\n"); return 0; } } format.bits = si->dma->samplebits = si->bits->value; format.rate = si->dma->speed = 44100; format.channels = si->dma->channels = si->channels->value; format.byte_format = AO_FMT_NATIVE; switch(si->dma->speed){ case 44100: si->dma->samples = 2048 * si->dma->channels; break; case 22050: si->dma->samples = 1024 * si->dma->channels; break; default: si->dma->samples = 512 * si->dma->channels; break; } if((device = ao_open_live(driver_id, &format, options)) == NULL){ switch(errno){ case AO_ENODRIVER: Com_Printf("ao: no driver for %d\n", driver_id); break; case AO_ENOTLIVE: Com_Printf("ao: not a valid live output device\n"); break; case AO_EBADOPTION: Com_Printf("ao: valid option has invalid key\n"); break; case AO_EOPENDEVICE: Com_Printf("ao: cannot open device\n"); break; case AO_EFAIL: Com_Printf("ao: something broke during ao_open_live\n"); break; case AO_ENOTFILE: Com_Printf("ao: not a file\n"); break; case AO_EOPENFILE: Com_Printf("ao: can't open file\n"); break; case AO_EFILEEXISTS: Com_Printf("ao: file exists already\n"); break; default: Com_Printf("ao: whoa, bad trip dude\n"); break; } return 0; } samplesize = si->dma->samplebits >> 3; si->dma->buffer = malloc(si->dma->samples * samplesize); memset(si->dma->buffer, 0, si->dma->samples * samplesize); si->dma->samplepos = 0; si->dma->submission_chunk = 1; si->Com_Printf("ao: buffer size is %d, %d samples\n", si->dma->samples * samplesize, si->dma->samples); snd_inited = 1; return 1; }
static void * ao_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, const struct config_param *param, GError **error) { struct ao_data *ad = g_new(struct ao_data, 1); ao_info *ai; const char *value; ad->options = NULL; ad->write_size = config_get_block_unsigned(param, "write_size", 1024); if (ao_output_ref == 0) { ao_initialize(); } ao_output_ref++; value = config_get_block_string(param, "driver", "default"); if (0 == strcmp(value, "default")) ad->driver = ao_default_driver_id(); else ad->driver = ao_driver_id(value); if (ad->driver < 0) { g_set_error(error, ao_output_quark(), 0, "\"%s\" is not a valid ao driver", value); g_free(ad); return NULL; } if ((ai = ao_driver_info(ad->driver)) == NULL) { g_set_error(error, ao_output_quark(), 0, "problems getting driver info"); g_free(ad); return NULL; } g_debug("using ao driver \"%s\" for \"%s\"\n", ai->short_name, config_get_block_string(param, "name", NULL)); value = config_get_block_string(param, "options", NULL); if (value != NULL) { gchar **options = g_strsplit(value, ";", 0); for (unsigned i = 0; options[i] != NULL; ++i) { gchar **key_value = g_strsplit(options[i], "=", 2); if (key_value[0] == NULL || key_value[1] == NULL) { g_set_error(error, ao_output_quark(), 0, "problems parsing options \"%s\"", options[i]); g_free(ad); return NULL; } ao_append_option(&ad->options, key_value[0], key_value[1]); g_strfreev(key_value); } g_strfreev(options); } return ad; }
void au_initEach(){ default_driver = ao_default_driver_id(); device = ao_open_live(default_driver, &format, NULL); /* signal(SIGTERM, au_deinitEach); */ }
void output_ao::setup(libconfig::Setting& setting) { int channels; int rate; int bps; std::string driver; if (setting.lookupValue("channels", channels)) { setting.remove("channels"); format.channels = channels; } else { format.channels = DEFAULT_GLOBAL_CHANNELS; } if (setting.lookupValue("rate", rate)) { setting.remove("rate"); format.rate = rate; } else { format.rate = 44100; } if (setting.lookupValue("bps", bps)) { setting.remove("bps"); format.bits = bps; } else { format.bits = 16; } format.byte_format = AO_FMT_LITTLE; if (setting.lookupValue("driver", driver)) { setting.remove("driver"); driver = ao_driver_id(driver.c_str()); } else { driver = ao_default_driver_id(); } int length = setting.getLength(); ao_option *current = NULL; for (int i = 0; i < length; i++) { libconfig::Setting& s = setting[i]; if (current == NULL) { current = new ao_option; options = current; } else { current->next = new ao_option; } std::string key = s.getName(); std::string value = s; current->key = new char[key.size() + 1]; current->value = new char[value.size() + 1]; ::strncpy(current->key, key.c_str(), key.size()); ::strncpy(current->value, value.c_str(), value.size()); } }
int main(int argc, char **argv) { int r, tmp, fi, random=0; char Buffer[1024]; char length_str[256], fade_str[256], volume[256], title_str[256]; char tmp_str[256]; char *tag; soundLowPass = 0; soundEcho = 0; soundQuality = 0; DetectSilence=1; silencelength=5; IgnoreTrackLength=0; DefaultLength=150000; TrailingSilence=1000; playforever=0; while((r=getopt(argc, argv, "hlsrieWL:t:"))>=0) { char *e; switch(r) { case 'h': printf("playgsf version %s (based on Highly Advanced version %s)\n\n", VERSION_STR, HA_VERSION_STR); printf("Usage: ./playgsf [options] files...\n\n"); printf(" -l Enable low pass filer\n"); printf(" -s Detect silence\n"); printf(" -L Set silence length in seconds (for detection). Default 5\n"); printf(" -t Set default track length in milliseconds. Default 150000 ms\n"); printf(" -i Ignore track length (use default length)\n"); printf(" -e Endless play\n"); printf(" -r Play files in random order\n"); printf(" -W output to 'output.wav' rather than soundcard\n"); printf(" -h Displays what you are reading right now\n"); return 0; break; case 'i': IgnoreTrackLength = 1; break; case 'l': soundLowPass = 1; break; case 's': DetectSilence = 1; break; case 'L': silencelength = strtol(optarg, &e, 0); if (e==optarg) { fprintf(stderr, "Bad value\n"); return 1; } break; case 'e': playforever = 1; break; case 't': DefaultLength = strtol(optarg, &e, 0); if (e==optarg) { fprintf(stderr, "Bad value\n"); return 1; } break; case 'r': random = 1; break; case 'W': fileoutput = 1; break; case '?': fprintf(stderr, "Unknown argument. try -h\n"); return 1; break; } } if (argc-optind<=0) { printf("No files specified! For help, try -h\n"); return 1; } if (random) { shuffle_list(&argv[optind], argc-optind); } printf("playgsf version %s (based on Highly Advanced version %s)\n\n", VERSION_STR, HA_VERSION_STR); signal(SIGINT, signal_handler); tag = (char*)malloc(50001); fi = optind; while (!g_must_exit && fi < argc) { decode_pos_ms = 0; seek_needed = -1; TrailingSilence=1000; r = GSFRun(argv[fi]); if (!r) { fi++; continue; } g_playing = 1; psftag_readfromfile((void*)tag, argv[fi]); BOLD(); printf("Filename: "); NORMAL(); printf("%s\n", basename(argv[fi])); BOLD(); printf("Channels: "); NORMAL(); printf("%d\n", sndNumChannels); BOLD(); printf("Sample rate: "); NORMAL(); printf("%d\n", sndSamplesPerSec); if (!psftag_getvar(tag, "title", title_str, sizeof(title_str)-1)) { BOLD(); printf("Title: "); NORMAL(); printf("%s\n", title_str); } if (!psftag_getvar(tag, "artist", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Artist: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "game", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Game: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "year", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Year: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "copyright", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Copyright: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "gsfby", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("GSF By: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "tagger", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Tagger: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "comment", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Comment: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "fade", fade_str, sizeof(fade_str)-1)) { FadeLength = LengthFromString(fade_str); BOLD(); printf("Fade: "); NORMAL(); printf("%s (%d ms)\n", fade_str, FadeLength); } if (!psftag_raw_getvar(tag, "length", length_str, sizeof(length_str)-1)) { TrackLength = LengthFromString(length_str) + FadeLength; BOLD(); printf("Length: "); NORMAL(); printf("%s (%d ms) ", length_str, TrackLength); if (IgnoreTrackLength) { printf("(ignored)"); TrackLength = DefaultLength; } printf("\n"); } else { TrackLength = DefaultLength; } /* Must be done after GSFrun so sndNumchannels and * sndSamplesPerSec are set to valid values */ ao_initialize(); ao_sample_format format_ao = { 16, sndSamplesPerSec, sndNumChannels, AO_FMT_LITTLE }; if(fileoutput) { snd_ao = ao_open_file(ao_driver_id("wav"), "output.wav", 1, &format_ao, NULL); } else { snd_ao = ao_open_live(ao_default_driver_id(), &format_ao, NULL); } while(g_playing) { int remaining = TrackLength - (int)decode_pos_ms; if (remaining<0) { // this happens during silence period remaining = 0; } EmulationLoop(); BOLD(); printf("Time: "); NORMAL(); printf("%02d:%02d.%02d ", (int)(decode_pos_ms/1000.0)/60, (int)(decode_pos_ms/1000.0)%60, (int)(decode_pos_ms/10.0)%100); if (!playforever) { /*BOLD();*/ printf("["); /*NORMAL();*/ printf("%02d:%02d.%02d", remaining/1000/60, (remaining/1000)%60, (remaining/10%100) ); /*BOLD();*/ printf("] of "); /*NORMAL();*/ printf("%02d:%02d.%02d ", TrackLength/1000/60, (TrackLength/1000)%60, (TrackLength/10%100)); } BOLD(); printf(" GBA Cpu: "); NORMAL(); printf("%02d%% ", cpupercent); printf(" \r"); fflush(stdout); } printf("\n--\n"); ao_close(snd_ao); fi++; } ao_shutdown(); return 0; }
int playback(FILE * streamfd, int pipefd) { killed = 0; signal(SIGUSR1, sighand); #ifndef EXTERN_ONLY if(!haskey(& rc, "extern")) { const char * freetrack = NULL; struct stream data; struct mad_decoder dec; #ifdef LIBAO static int ao_initialized = 0; if(!ao_initialized) { ao_initialize(); ao_initialized = !0; } #else unsigned arg; int fd; #endif memset(& data, 0, sizeof(struct stream)); /* Check if there's a stream timeout configured and set it up for timed reads later. */ data.timeout = -1; if(haskey(& rc, "stream-timeout")) { const char * timeout = value(& rc, "stream-timeout"); data.timeout = atoi(timeout); if(data.timeout <= 0) { if(data.timeout < 0) fputs("Invalid stream-timeout.\n", stderr); data.timeout = -1; } } data.streamfd = streamfd; data.parent = getppid(); data.pipefd = pipefd; fcntl(pipefd, F_SETFL, O_NONBLOCK); #ifdef LIBAO data.driver_id = ao_default_driver_id(); if(-1 == data.driver_id) { fputs("Unable to find any usable output device!\n", stderr); return 0; } data.fmt.bits = 16; data.fmt.rate = 44100; data.fmt.channels = 2; data.fmt.byte_format = AO_FMT_NATIVE; data.device = ao_open_live(data.driver_id,&data.fmt,NULL); if(NULL == data.device) { fprintf(stderr, "Unable to open device. %s.\n", strerror(errno)); return 0; } #else data.audiofd = fd = open(value(& rc, "device"), O_WRONLY); if(-1 == data.audiofd) { fprintf( stderr, "Couldn't open %s! %s.\n", value(& rc, "device"), strerror(errno) ); return 0; } arg = 16; /* 16 bits */ ioctl(data.audiofd, SOUND_PCM_WRITE_BITS, & arg); #endif freetrack = value(& track, "freeTrackURL"); if(freetrack && strlen(freetrack) > 0 && haskey(& rc, "download")) { char * dnam; int rv; data.finpath = strdup(meta(value(& rc, "download"), M_RELAXPATH, & track)); assert(data.finpath != NULL); data.tmppath = strjoin("", data.finpath, ".streaming", NULL); assert(data.tmppath != NULL); dnam = strdup(data.tmppath); rv = dnam ? mkpath(dirname(dnam)) : -1; free(dnam); if(access(data.tmppath, R_OK) == -1) { data.dump = (rv == 0) ? fopen(data.tmppath, "w") : NULL; if(!data.dump) fprintf(stderr, "Can't write download to %s.\n", data.tmppath); } else { data.dump = NULL; } } mad_decoder_init(& dec, & data, input, NULL, NULL, output, NULL, NULL); mad_decoder_run(& dec, MAD_DECODER_MODE_SYNC); #ifndef LIBAO close(fd); #endif mad_decoder_finish(& dec); if(data.dump) { fclose(data.dump); if(killed) { unlink(data.tmppath); } else { int rv; #ifdef TAGLIB TagLib_File *tagme = taglib_file_new_type(data.tmppath, TagLib_File_MPEG); if(tagme != NULL) { TagLib_Tag *tag = taglib_file_tag(tagme); taglib_tag_set_title(tag, value(&track, "title")); taglib_tag_set_artist(tag, value(&track, "creator")); taglib_tag_set_album(tag, value(&track, "album")); taglib_file_save(tagme); taglib_file_free(tagme); } #endif if(haskey(& rc, "pp-cmd")) { const char *ppcmd = value(& rc, "pp-cmd"); size_t ppcmdlen = strlen(ppcmd); char *path = shellescape(data.tmppath); assert(path != NULL); size_t pathlen = strlen(path); char *command = malloc(ppcmdlen + pathlen + 2); assert(command != NULL); memcpy(command, ppcmd, ppcmdlen); command[ppcmdlen] = ' '; memcpy(command + ppcmdlen + 1, path, pathlen); command[ppcmdlen + 1 + pathlen] = 0; run(command); free(path); free(command); } rv = rename(data.tmppath, data.finpath); if (rv == -1) fprintf(stderr, "Can't rename %s to %s\n", data.tmppath, data.finpath); } free(data.tmppath); free(data.finpath); } } else #endif { pid_t ppid = getppid(), cpid = 0; const char * cmd = meta(value(& rc, "extern"), M_SHELLESC, & track); FILE * ext = openpipe(cmd, & cpid); unsigned char * buf; if(!ext) { fprintf(stderr, "Failed to execute external player (%s). %s.\n", cmd, strerror(errno)); return 0; } if(!(buf = calloc(BUFSIZE + 1, sizeof(unsigned char)))) { fputs("Couldn't allocate enough memory for input buffer.\n", stderr); fclose(ext); return 0; } while(!feof(streamfd)) { signed nbyte = fread(buf, sizeof(unsigned char), BUFSIZE, streamfd); if(nbyte > 0) { fwrite(buf, sizeof(unsigned char), nbyte, ext); fflush(ext); } if(kill(ppid, 0) == -1 && errno == ESRCH) break; if(killed) break; } free(buf); fclose(ext); waitpid(cpid, NULL, 0); } return !0; }
void cAudio::run() { lt_info("====================== start decoder thread ================================\n"); /* libavcodec & friends */ av_register_all(); AVCodec *codec; AVFormatContext *avfc = NULL; AVInputFormat *inp; AVFrame *frame; uint8_t *inbuf = (uint8_t *)av_malloc(INBUF_SIZE); AVPacket avpkt; int ret, driver; /* libao */ ao_info *ai; // ao_device *adevice; // ao_sample_format sformat; /* resample */ SwrContext *swr = NULL; uint8_t *obuf = NULL; int obuf_sz = 0; /* in samples */ int obuf_sz_max = 0; int o_ch, o_sr; /* output channels and sample rate */ uint64_t o_layout; /* output channels layout */ char tmp[64] = "unknown"; curr_pts = 0; av_init_packet(&avpkt); inp = av_find_input_format("mpegts"); AVIOContext *pIOCtx = avio_alloc_context(inbuf, INBUF_SIZE, // internal Buffer and its size 0, // bWriteable (1=true,0=false) NULL, // user data; will be passed to our callback functions _my_read, // read callback NULL, // write callback NULL); // seek callback avfc = avformat_alloc_context(); avfc->pb = pIOCtx; avfc->iformat = inp; avfc->probesize = 188*5; thread_started = true; if (avformat_open_input(&avfc, NULL, inp, NULL) < 0) { lt_info("%s: avformat_open_input() failed.\n", __func__); goto out; } ret = avformat_find_stream_info(avfc, NULL); lt_debug("%s: avformat_find_stream_info: %d\n", __func__, ret); if (avfc->nb_streams != 1) { lt_info("%s: nb_streams: %d, should be 1!\n", __func__, avfc->nb_streams); goto out; } if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type); c = avfc->streams[0]->codec; codec = avcodec_find_decoder(c->codec_id); if (!codec) { lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id)); goto out; } if (avcodec_open2(c, codec, NULL) < 0) { lt_info("%s: avcodec_open2() failed\n", __func__); goto out; } frame = av_frame_alloc(); if (!frame) { lt_info("%s: avcodec_alloc_frame failed\n", __func__); goto out2; } /* output sample rate, channels, layout could be set here if necessary */ o_ch = c->channels; /* 2 */ o_sr = c->sample_rate; /* 48000 */ o_layout = c->channel_layout; /* AV_CH_LAYOUT_STEREO */ if (sformat.channels != o_ch || sformat.rate != o_sr || sformat.byte_format != AO_FMT_NATIVE || sformat.bits != 16 || adevice == NULL) { driver = ao_default_driver_id(); sformat.bits = 16; sformat.channels = o_ch; sformat.rate = o_sr; sformat.byte_format = AO_FMT_NATIVE; sformat.matrix = 0; if (adevice) ao_close(adevice); adevice = ao_open_live(driver, &sformat, NULL); ai = ao_driver_info(driver); lt_info("%s: changed params ch %d srate %d bits %d adevice %p\n", __func__, o_ch, o_sr, 16, adevice);; lt_info("libao driver: %d name '%s' short '%s' author '%s'\n", driver, ai->name, ai->short_name, ai->author); } #if 0 lt_info(" driver options:"); for (int i = 0; i < ai->option_count; ++i) fprintf(stderr, " %s", ai->options[i]); fprintf(stderr, "\n"); #endif av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt); lt_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n", avcodec_get_name(c->codec_id), c->sample_fmt, tmp, c->sample_rate, c->channels); swr = swr_alloc_set_opts(swr, o_layout, AV_SAMPLE_FMT_S16, o_sr, /* output */ c->channel_layout, c->sample_fmt, c->sample_rate, /* input */ 0, NULL); if (! swr) { lt_info("could not alloc resample context\n"); goto out3; } swr_init(swr); while (thread_started) { int gotframe = 0; if (av_read_frame(avfc, &avpkt) < 0) break; avcodec_decode_audio4(c, frame, &gotframe, &avpkt); if (gotframe && thread_started) { int out_linesize; obuf_sz = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + frame->nb_samples, o_sr, c->sample_rate, AV_ROUND_UP); if (obuf_sz > obuf_sz_max) { lt_info("obuf_sz: %d old: %d\n", obuf_sz, obuf_sz_max); av_free(obuf); if (av_samples_alloc(&obuf, &out_linesize, o_ch, frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) { lt_info("av_samples_alloc failed\n"); av_free_packet(&avpkt); break; /* while (thread_started) */ } obuf_sz_max = obuf_sz; } obuf_sz = swr_convert(swr, &obuf, obuf_sz, (const uint8_t **)frame->extended_data, frame->nb_samples); curr_pts = av_frame_get_best_effort_timestamp(frame); lt_debug("%s: pts 0x%" PRIx64 " %3f\n", __func__, curr_pts, curr_pts/90000.0); int o_buf_sz = av_samples_get_buffer_size(&out_linesize, o_ch, obuf_sz, AV_SAMPLE_FMT_S16, 1); ao_play(adevice, (char *)obuf, o_buf_sz); } av_free_packet(&avpkt); } // ao_close(adevice); /* can take long :-( */ av_free(obuf); swr_free(&swr); out3: av_frame_free(&frame); out2: avcodec_close(c); c = NULL; out: avformat_close_input(&avfc); av_free(pIOCtx->buffer); av_free(pIOCtx); lt_info("======================== end decoder thread ================================\n"); }
int main(int argc, char **argv) { int status = 0; struct params par; int opt; signal(SIGHUP, interrupt_handler); signal(SIGINT, interrupt_handler); signal(SIGQUIT, interrupt_handler); ao_initialize(); driver_id = ao_default_driver_id(); memset(¤t_sample_format, 0, sizeof(current_sample_format)); if (argc == 1) { /* We were invoked with no arguments */ usage(argv[0]); goto done; } again: { struct params default_par = DEFAULT_PARAMS; memcpy(&par, &default_par, sizeof(par)); } while ((opt = getopt(argc, argv, "-D:F:L:M:S:b:d:f:o:@:hrv")) != -1) { switch (opt) { case '@': if (play_playlist(optarg, &par)) { status = 1; goto done; } break; case 'D': par.fade_delay = atof(optarg); break; case 'F': par.fade_time = atof(optarg); break; case 'L': par.loop_count = atoi(optarg); break; case 'M': par.min_time = atof(optarg); par.loop_count = -1; break; case 'S': par.stream_index = atoi(optarg); break; case 'b': if (!buffer) buffer_size_kb = atoi(optarg); break; case 'd': driver_id = ao_driver_id(optarg); if (driver_id < 0) { fprintf(stderr, "Invalid output driver \"%s\"\n", optarg); status = 1; goto done; } break; case 'f': out_filename = optarg; break; case 'h': usage(argv[0]); goto done; case 'o': add_driver_option(optarg); break; case 'r': repeat = 1; break; case 'v': verbose = 1; break; default: goto done; } } argc -= optind; argv += optind; for (opt = 0; opt < argc; ++opt) { if (play_file(argv[opt], &par)) { status = 1; goto done; } } if (repeat) { optind = 0; goto again; } done: if (device) ao_close(device); if (buffer) free(buffer); ao_free_options(device_options); ao_shutdown(); return status; }
/* play aac stream * @param streamed data * @param received bytes * @param extra data (player data) * @return received bytes or less on error */ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size, void *stream) { const char *data = ptr; struct audioPlayer *player = stream; if (BarPlayerCheckPauseQuit (player) || !BarPlayerBufferFill (player, data, size)) { return WAITRESS_CB_RET_ERR; } if (player->mode == PLAYER_RECV_DATA) { short int *aacDecoded; NeAACDecFrameInfo frameInfo; size_t i; while (player->sampleSizeCurr < player->sampleSizeN && (player->bufferFilled - player->bufferRead) >= player->sampleSize[player->sampleSizeCurr]) { /* going through this loop can take up to a few seconds => * allow earlier thread abort */ if (BarPlayerCheckPauseQuit (player)) { return WAITRESS_CB_RET_ERR; } /* decode frame */ aacDecoded = NeAACDecDecode(player->aacHandle, &frameInfo, &player->buffer[player->bufferRead], player->sampleSize[player->sampleSizeCurr]); player->bufferRead += player->sampleSize[player->sampleSizeCurr]; ++player->sampleSizeCurr; if (frameInfo.error != 0) { /* skip this frame, songPlayed will be slightly off if this * happens */ BarUiMsg (player->settings, MSG_ERR, "Decoding error: %s\n", NeAACDecGetErrorMessage (frameInfo.error)); continue; } /* assuming data in stsz atom is correct */ assert (frameInfo.bytesconsumed == player->sampleSize[player->sampleSizeCurr-1]); for (i = 0; i < frameInfo.samples; i++) { aacDecoded[i] = applyReplayGain (aacDecoded[i], player->scale); } /* ao_play needs bytes: 1 sample = 16 bits = 2 bytes */ ao_play (player->audioOutDevice, (char *) aacDecoded, frameInfo.samples * 2); /* add played frame length to played time, explained below */ player->songPlayed += (unsigned long long int) frameInfo.samples * (unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR / (unsigned long long int) player->samplerate / (unsigned long long int) player->channels; } if (player->sampleSizeCurr >= player->sampleSizeN) { /* no more frames, drop data */ player->bufferRead = player->bufferFilled; } } else { if (player->mode == PLAYER_INITIALIZED) { while (player->bufferRead+4 < player->bufferFilled) { if (memcmp (player->buffer + player->bufferRead, "esds", 4) == 0) { player->mode = PLAYER_FOUND_ESDS; player->bufferRead += 4; break; } player->bufferRead++; } } if (player->mode == PLAYER_FOUND_ESDS) { /* FIXME: is this the correct way? */ /* we're gonna read 10 bytes */ while (player->bufferRead+1+4+5 < player->bufferFilled) { if (memcmp (player->buffer + player->bufferRead, "\x05\x80\x80\x80", 4) == 0) { ao_sample_format format; int audioOutDriver; /* +1+4 needs to be replaced by <something>! */ player->bufferRead += 1+4; char err = NeAACDecInit2 (player->aacHandle, player->buffer + player->bufferRead, 5, &player->samplerate, &player->channels); player->bufferRead += 5; if (err != 0) { BarUiMsg (player->settings, MSG_ERR, "Error while initializing audio decoder " "(%i)\n", err); return WAITRESS_CB_RET_ERR; } audioOutDriver = ao_default_driver_id(); memset (&format, 0, sizeof (format)); format.bits = 16; format.channels = player->channels; format.rate = player->samplerate; format.byte_format = AO_FMT_NATIVE; if ((player->audioOutDevice = ao_open_live (audioOutDriver, &format, NULL)) == NULL) { /* we're not interested in the errno */ player->aoError = 1; BarUiMsg (player->settings, MSG_ERR, "Cannot open audio device\n"); return WAITRESS_CB_RET_ERR; } player->mode = PLAYER_AUDIO_INITIALIZED; break; } player->bufferRead++; } } if (player->mode == PLAYER_AUDIO_INITIALIZED) { while (player->bufferRead+4+8 < player->bufferFilled) { if (memcmp (player->buffer + player->bufferRead, "stsz", 4) == 0) { player->mode = PLAYER_FOUND_STSZ; player->bufferRead += 4; /* skip version and unknown */ player->bufferRead += 8; break; } player->bufferRead++; } } /* get frame sizes */ if (player->mode == PLAYER_FOUND_STSZ) { while (player->bufferRead+4 < player->bufferFilled) { /* how many frames do we have? */ if (player->sampleSizeN == 0) { /* mp4 uses big endian, convert */ memcpy (&player->sampleSizeN, player->buffer + player->bufferRead, sizeof (uint32_t)); player->sampleSizeN = bigToHostEndian32 (player->sampleSizeN); player->sampleSize = malloc (player->sampleSizeN * sizeof (*player->sampleSize)); assert (player->sampleSize != NULL); player->bufferRead += sizeof (uint32_t); player->sampleSizeCurr = 0; /* set up song duration (assuming one frame always contains * the same number of samples) * calculation: channels * number of frames * samples per * frame / samplerate */ /* FIXME: Hard-coded number of samples per frame */ player->songDuration = (unsigned long long int) player->sampleSizeN * 4096LL * (unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR / (unsigned long long int) player->samplerate / (unsigned long long int) player->channels; break; } else { memcpy (&player->sampleSize[player->sampleSizeCurr], player->buffer + player->bufferRead, sizeof (uint32_t)); player->sampleSize[player->sampleSizeCurr] = bigToHostEndian32 ( player->sampleSize[player->sampleSizeCurr]); player->sampleSizeCurr++; player->bufferRead += sizeof (uint32_t); } /* all sizes read, nearly ready for data mode */ if (player->sampleSizeCurr >= player->sampleSizeN) { player->mode = PLAYER_SAMPLESIZE_INITIALIZED; break; } } } /* search for data atom and let the show begin... */ if (player->mode == PLAYER_SAMPLESIZE_INITIALIZED) { while (player->bufferRead+4 < player->bufferFilled) { if (memcmp (player->buffer + player->bufferRead, "mdat", 4) == 0) { player->mode = PLAYER_RECV_DATA; player->sampleSizeCurr = 0; player->bufferRead += 4; break; } player->bufferRead++; } } } BarPlayerBufferMove (player); return WAITRESS_CB_RET_OK; }
// Initialize the libPOLY global state. Return 0 on success, 1 on error. int poly_init(int bitdepth, int channels, int bitrate, int max_generators, const char *filename) { // Make sure arguments are valid: if(!((bitdepth == 8) || (bitdepth == 16) || (bitdepth == 24))) { DEBUG_MSG("bitdepth not one of 8, 16, 26"); errno = EINVAL; return 1; } if(!((channels == 1) || (channels == 2))) { DEBUG_MSG("channels not one of 1, 2"); errno = EINVAL; return 1; } if(!((bitrate == 44100) || (bitrate == 48000) || (bitrate == 96000))) { DEBUG_MSG("bitrate not one of 44100, 48000, 96000"); errno = EINVAL; return 1; } if(max_generators <= 0) { DEBUG_MSG("max_generators <= 0"); errno = EINVAL; return 1; } // Initialize libao: ao_initialize(); poly_ao_init = 1; poly_playback = 0; poly_max_generators = max_generators; poly_time = 0; int driver; // Populate the format struct: poly_format = calloc(1, sizeof(*poly_format)); if(poly_format == NULL) { DEBUG_MSG("calloc for *poly_format failed"); errno = ENOMEM; return 1; } poly_format->bits = bitdepth; poly_format->channels = channels; poly_format->rate = bitrate; poly_format->byte_format = AO_FMT_NATIVE; // Are we using a sound card? if(filename == NULL) { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN32__) || defined(__WIN64__) || defined(__WINDOWS__) driver = ao_default_driver_id(); if(driver == -1) { DEBUG_MSG("ao_default_driver_id() failed"); errno = ENODEV; free(poly_format); return 1; } #else driver = ao_driver_id("alsa"); if(driver == -1) { DEBUG_MSG("ao_driver_id() failed"); errno = ENODEV; free(poly_format); return 1; } #endif poly_card = ao_open_live(driver, poly_format, NULL); if(poly_card == NULL) { switch(errno) { case AO_ENODRIVER: DEBUG_MSG("invalid driver"); break; case AO_ENOTLIVE: DEBUG_MSG("file driver passed, live driver expected"); break; case AO_EBADOPTION: DEBUG_MSG("invalid libao option, check local libao config"); break; case AO_EOPENDEVICE: DEBUG_MSG("can't open device"); break; default: DEBUG_MSG("unknown libao error"); break; } free(poly_format); return 1; } } // We're using an output file: else { driver = ao_driver_id("wav"); if(driver == -1) { DEBUG_MSG("libao error, can't open WAV driver"); errno = ENODEV; free(poly_format); return 1; } poly_card = ao_open_file(driver, filename, 1, poly_format, NULL); if(poly_card == NULL) { switch(errno) { case AO_ENODRIVER: DEBUG_MSG("invalid driver"); break; case AO_ENOTFILE: DEBUG_MSG("non-file driver passed"); break; case AO_EBADOPTION: DEBUG_MSG("invalid libao option, check local libao config"); break; case AO_EOPENFILE: DEBUG_MSG("can't open file"); break; default: DEBUG_MSG("unknown libao error"); break; } free(poly_format); return 1; } } poly_generators = calloc(poly_max_generators, sizeof(*poly_generators)); return 0; }
static PyObject* py_ao_default_driver_id(PyObject *self, PyObject *args) { /* Passed with METH_NOARGS */ return PyInt_FromLong(ao_default_driver_id()); }
int parse_cmdline_options (int argc, char **argv, ogg123_options_t *ogg123_opts, file_option_t *file_opts) { int option_index = 1; ao_option *temp_options = NULL; ao_option ** current_options = &temp_options; ao_info *info; int temp_driver_id = -1; audio_device_t *current; int ret; while (-1 != (ret = getopt_long(argc, argv, "b:c::d:f:hl:k:K:o:p:qrRvVx:y:zZ@:", long_options, &option_index))) { switch (ret) { case 0: if(!strcmp(long_options[option_index].name, "audio-buffer")) { ogg123_opts->buffer_size = 1024 * atoi(optarg); } else { status_error(_("Internal error parsing command line options.\n")); exit(1); } break; case 'b': ogg123_opts->input_buffer_size = atoi(optarg) * 1024; if (ogg123_opts->input_buffer_size < MIN_INPUT_BUFFER_SIZE * 1024) { status_error(_("Input buffer size smaller than minimum size of %dkB."), MIN_INPUT_BUFFER_SIZE); ogg123_opts->input_buffer_size = MIN_INPUT_BUFFER_SIZE * 1024; } break; case 'c': if (optarg) { char *tmp = strdup (optarg); parse_code_t pcode = parse_line(file_opts, tmp); if (pcode != parse_ok) status_error(_("=== Error \"%s\" while parsing config option from command line.\n" "=== Option was: %s\n"), parse_error_string(pcode), optarg); free (tmp); } else { /* not using the status interface here */ fprintf (stdout, _("Available options:\n")); file_options_describe(file_opts, stdout); exit (0); } break; case 'd': temp_driver_id = ao_driver_id(optarg); if (temp_driver_id < 0) { status_error(_("=== No such device %s.\n"), optarg); exit(1); } current = append_audio_device(ogg123_opts->devices, temp_driver_id, NULL, NULL); if(ogg123_opts->devices == NULL) ogg123_opts->devices = current; current_options = ¤t->options; break; case 'f': if (temp_driver_id >= 0) { info = ao_driver_info(temp_driver_id); if (info->type == AO_TYPE_FILE) { free(current->filename); current->filename = strdup(optarg); } else { status_error(_("=== Driver %s is not a file output driver.\n"), info->short_name); exit(1); } } else { status_error(_("=== Cannot specify output file without specifying a driver.\n")); exit (1); } break; case 'k': set_seek_opt(ogg123_opts, optarg); break; case 'K': ogg123_opts->endpos = strtotime(optarg); break; case 'l': ogg123_opts->delay = atoi(optarg); break; case 'o': if (optarg && !add_ao_option(current_options, optarg)) { status_error(_("=== Incorrect option format: %s.\n"), optarg); exit(1); } break; case 'h': cmdline_usage(); exit(0); break; case 'p': ogg123_opts->input_prebuffer = atof (optarg); if (ogg123_opts->input_prebuffer < 0.0f || ogg123_opts->input_prebuffer > 100.0f) { status_error (_("--- Prebuffer value invalid. Range is 0-100.\n")); ogg123_opts->input_prebuffer = ogg123_opts->input_prebuffer < 0.0f ? 0.0f : 100.0f; } break; case 'q': ogg123_opts->verbosity = 0; break; case 'r': ogg123_opts->repeat = 1; break; case 'R': ogg123_opts->remote = 1; ogg123_opts->verbosity = 0; break; case 'v': ogg123_opts->verbosity++; break; case 'V': status_error(_("ogg123 from %s %s"), PACKAGE, VERSION); exit(0); break; case 'x': ogg123_opts->nth = atoi(optarg); if (ogg123_opts->nth == 0) { status_error(_("--- Cannot play every 0th chunk!\n")); ogg123_opts->nth = 1; } break; case 'y': ogg123_opts->ntimes = atoi(optarg); if (ogg123_opts->ntimes == 0) { status_error(_("--- Cannot play every chunk 0 times.\n" "--- To do a test decode, use the null output driver.\n")); ogg123_opts->ntimes = 1; } break; case 'z': ogg123_opts->shuffle = 1; break; case 'Z': ogg123_opts->repeat = ogg123_opts->shuffle = 1; break; case '@': if (playlist_append_from_file(ogg123_opts->playlist, optarg) == 0) status_error(_("--- Cannot open playlist file %s. Skipped.\n"), optarg); break; case '?': break; default: cmdline_usage(); exit(1); } } /* Sanity check bad option combinations */ if (ogg123_opts->endpos > 0.0 && ogg123_opts->seekoff > ogg123_opts->endpos) { status_error(_("=== Option conflict: End time is before start time.\n")); exit(1); } /* Add last device to device list or use the default device */ if (temp_driver_id < 0) { /* First try config file setting */ if (ogg123_opts->default_device) { temp_driver_id = ao_driver_id(ogg123_opts->default_device); if (temp_driver_id < 0) status_error(_("--- Driver %s specified in configuration file invalid.\n"), ogg123_opts->default_device); } /* Then try libao autodetect */ if (temp_driver_id < 0) temp_driver_id = ao_default_driver_id(); /* Finally, give up */ if (temp_driver_id < 0) { status_error(_("=== Could not load default driver and no driver specified in config file. Exiting.\n")); exit(1); } ogg123_opts->devices = append_audio_device(ogg123_opts->devices, temp_driver_id, temp_options, NULL); } /* if verbosity has been altered, add options to drivers... */ { audio_device_t *head = ogg123_opts->devices; while (head){ if(ogg123_opts->verbosity>3) ao_append_global_option("debug",NULL); if(ogg123_opts->verbosity>2) ao_append_option(&(head->options),"verbose",NULL); if(ogg123_opts->verbosity==0) ao_append_option(&(head->options),"quiet",NULL); head = head->next_device; } } return optind; }