static int init(int rate_hz, int channels, int format, int flags) { int err; int frag_spec; if( (err=arts_init()) ) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ARTS_CantInit, arts_error_text(err)); return 0; } mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ARTS_ServerConnect); /* * arts supports 8bit unsigned and 16bit signed sample formats * (16bit apparently in little endian format, even in the case * when artsd runs on a big endian cpu). * * Unsupported formats are translated to one of these two formats * using mplayer's audio filters. */ switch (format) { case AF_FORMAT_U8: case AF_FORMAT_S8: format = AF_FORMAT_U8; break; default: format = AF_FORMAT_S16_LE; /* artsd always expects little endian?*/ break; } ao_data.format = format; ao_data.channels = channels; ao_data.samplerate = rate_hz; ao_data.bps = (rate_hz*channels); if(format != AF_FORMAT_U8 && format != AF_FORMAT_S8) ao_data.bps*=2; stream=arts_play_stream(rate_hz, OBTAIN_BITRATE(format), channels, "MPlayer"); if(stream == NULL) { mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ARTS_CantOpenStream); arts_free(); return 0; } /* Set the stream to blocking: it will not block anyway, but it seems */ /* to be working better */ arts_stream_set(stream, ARTS_P_BLOCKING, 1); frag_spec = ARTS_PACKET_SIZE_LOG2 | ARTS_PACKETS << 16; arts_stream_set(stream, ARTS_P_PACKET_SETTINGS, frag_spec); ao_data.buffersize = arts_stream_get(stream, ARTS_P_BUFFER_SIZE); mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ARTS_StreamOpen); mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ARTS_BufferSize, ao_data.buffersize); mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ARTS_BufferSize, arts_stream_get(stream, ARTS_P_PACKET_SIZE)); return 1; }
static int acntl(int request, void *arg) { int tmp, tmp1, samples; switch(request) { case PM_REQ_DISCARD: /* Discard stream */ arts_close_stream(stream); stream=NULL; return 0; case PM_REQ_RATE: /* Change sample rate */ arts_close_stream(stream); tmp = (dpm.encoding & PE_16BIT) ? 16 : 8; tmp1 = (dpm.encoding & PE_MONO) ? 1 : 2; stream = arts_play_stream(*(int*)arg, LE_LONG(tmp), tmp1, "timidity"); server_buffer = arts_stream_get(stream, ARTS_P_SERVER_LATENCY) * dpm.rate * (tmp/8) * tmp1 / 1000; return 0; case PM_REQ_GETQSIZ: /* Get maximum queue size */ *(int*)arg = arts_stream_get(stream, ARTS_P_BUFFER_SIZE); return 0; case PM_REQ_SETQSIZ: /* Set queue size */ *(int*)arg = arts_stream_set(stream, ARTS_P_BUFFER_SIZE, *(int*)arg); return 0; case PM_REQ_GETFRAGSIZ: /* Get device fragment size */ *(int*)arg = arts_stream_get(stream, ARTS_P_PACKET_SIZE); return 0; case PM_REQ_GETSAMPLES: /* Get current play sample */ tmp = arts_stream_get(stream, ARTS_P_BUFFER_SIZE) - arts_stream_get(stream, ARTS_P_BUFFER_SPACE) + server_buffer; samples = output_count - tmp; if(samples < 0) samples = 0; if(!(dpm.encoding & PE_MONO)) samples >>= 1; if(dpm.encoding & PE_16BIT) samples >>= 1; *(int*)arg = samples; return 0; case PM_REQ_GETFILLABLE: /* Get fillable device queue size */ *(int*)arg = arts_stream_get(stream, ARTS_P_BUFFER_SPACE); return 0; case PM_REQ_GETFILLED: /* Get filled device queue size */ *(int*)arg = arts_stream_get(stream, ARTS_P_BUFFER_SIZE) - arts_stream_get(stream, ARTS_P_BUFFER_SPACE); return 0; /* The following are not (yet) implemented: */ case PM_REQ_FLUSH: /* Wait until playback is complete */ case PM_REQ_MIDI: /* Send MIDI event */ case PM_REQ_INST_NAME: /* Get instrument name */ return -1; case PM_REQ_OUTPUT_FINISH: /* Sent after last output_data */ case PM_REQ_PLAY_START: /* Called just before playing */ case PM_REQ_PLAY_END: /* Called just after playing */ return 0; } return -1; }
static int op_arts_buffer_space(void) { int space; space = arts_stream_get(arts_stream, ARTS_P_BUFFER_SPACE); if (space < 0) return -1; return space; }
static int op_arts_open(sample_format_t sf, const channel_position_t *channel_map) { int buffer_time, server_latency, total_latency; int blocking; arts_sf = sf; arts_stream = arts_play_stream(sf_get_rate(arts_sf), sf_get_bits(arts_sf), sf_get_channels(arts_sf), "cmus"); blocking = arts_stream_set(arts_stream, ARTS_P_BLOCKING, 0); if (blocking) { } arts_buffer_size = arts_stream_get(arts_stream, ARTS_P_BUFFER_SIZE); if (arts_buffer_size < 0) { } buffer_time = arts_stream_get(arts_stream, ARTS_P_BUFFER_TIME); server_latency = arts_stream_get(arts_stream, ARTS_P_SERVER_LATENCY); total_latency = arts_stream_get(arts_stream, ARTS_P_TOTAL_LATENCY); d_print("buffer_time: %d\n", buffer_time); d_print("server_latency: %d\n", server_latency); d_print("total_latency: %d\n", total_latency); return 0; }
static float get_delay(void) { return ((float) (ao_data.buffersize - arts_stream_get(stream, ARTS_P_BUFFER_SPACE))) / ((float) ao_data.bps); }
static int get_space(void) { return arts_stream_get(stream, ARTS_P_BUFFER_SPACE); }
static int ARTSC_OpenAudio(_THIS, SDL_AudioSpec *spec) { int bits, frag_spec; Uint16 test_format, format; /* Reset the timer synchronization flag */ frame_ticks = 0.0; mixbuf = NULL; /* Try for a closest match on audio format */ format = 0; bits = 0; for ( test_format = SDL_FirstAudioFormat(spec->format); ! format && test_format; ) { #ifdef DEBUG_AUDIO fprintf(stderr, "Trying format 0x%4.4x\n", test_format); #endif switch ( test_format ) { case AUDIO_U8: bits = 8; format = 1; break; case AUDIO_S16LSB: bits = 16; format = 1; break; default: format = 0; break; } if ( ! format ) { test_format = SDL_NextAudioFormat(); } } if ( format == 0 ) { SDL_SetError("Couldn't find any hardware audio formats"); return(-1); } spec->format = test_format; stream = arts_play_stream(spec->freq, bits, spec->channels, "SDL"); /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(spec); /* Determine the power of two of the fragment size */ for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec ); if ( (0x01<<frag_spec) != spec->size ) { SDL_SetError("Fragment size must be a power of two"); return(-1); } frag_spec |= 0x00020000; /* two fragments, for low latency */ #ifdef ARTS_P_PACKET_SETTINGS arts_stream_set(stream, ARTS_P_PACKET_SETTINGS, frag_spec); #else arts_stream_set(stream, ARTS_P_PACKET_SIZE, frag_spec&0xffff); arts_stream_set(stream, ARTS_P_PACKET_COUNT, frag_spec>>16); #endif spec->size = arts_stream_get(stream, ARTS_P_PACKET_SIZE); /* Allocate mixing buffer */ mixlen = spec->size; mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); if ( mixbuf == NULL ) { return(-1); } memset(mixbuf, spec->silence, spec->size); /* Get the parent process id (we're the parent of the audio thread) */ parent = getpid(); /* We're ready to rock and roll. :-) */ return(0); }
static int open_output(void) { int i, include_enc, exclude_enc; int sample_width, channels; include_enc = 0; exclude_enc = PE_ULAW|PE_ALAW|PE_BYTESWAP; /* They can't mean these */ if(dpm.encoding & PE_16BIT) include_enc |= PE_SIGNED; else exclude_enc |= PE_SIGNED; dpm.encoding = validate_encoding(dpm.encoding, include_enc, exclude_enc); sample_width = (dpm.encoding & PE_16BIT) ? 16 : 8; channels = (dpm.encoding & PE_MONO) ? 1 : 2; /* Open the audio device */ switch (arts_init_state) { case 0: if((i = arts_init()) != 0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, arts_error_text(i)); return -1; } arts_init_state = 1; break; case 2: ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "TiMidity aRts bug: open_output() after close_output() not supported"); return -1; } stream = arts_play_stream(dpm.rate, LE_LONG(sample_width), channels, "timidity"); if(stream == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); return -1; } arts_stream_set(stream, ARTS_P_BLOCKING, 1); server_buffer = arts_stream_get(stream, ARTS_P_SERVER_LATENCY) * dpm.rate * (sample_width/8) * channels / 1000; output_count = 0; return 0; /* "this aRts function isnot yet implemented" * if (dpm.extra_param[0]) { i = arts_stream_set(stream, ARTS_P_PACKET_COUNT, dpm.extra_param[0]); if (i < 0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, arts_error_text(i)); return 1; } } return 0; * */ }
/* public methods (static but exported through the sysdep_dsp or plugin struct) */ static void *arts_dsp_create(const void *flags) { int i, j, result, bits, channels, block; struct arts_dsp_priv_data *priv = NULL; struct sysdep_dsp_struct *dsp = NULL; const struct sysdep_dsp_create_params *params = flags; /* allocate the dsp struct */ if (!(dsp = calloc(1, sizeof(struct sysdep_dsp_struct)))) { fprintf(stderr, "error malloc failed for struct sysdep_dsp_struct\n"); return NULL; } /* alloc private data */ if(!(priv = calloc(1, sizeof(struct arts_dsp_priv_data)))) { fprintf(stderr, "error malloc failed for struct arts_dsp_priv_data\n"); arts_dsp_destroy(dsp); return NULL; } /* fill in the functions and some data */ priv->stream = NULL; dsp->_priv = priv; dsp->write = arts_dsp_write; dsp->destroy = arts_dsp_destroy; dsp->hw_info.type = params->type; dsp->hw_info.samplerate = params->samplerate; result = arts_init(); if (result < 0) { fprintf(stderr, "arts_init error: %s\n", arts_error_text(result)); arts_dsp_destroy(dsp); return NULL; } bits = (dsp->hw_info.type & SYSDEP_DSP_16BIT) ? 16 : 8; channels = (dsp->hw_info.type & SYSDEP_DSP_STEREO) ? 2 : 1; priv->stream = arts_play_stream(dsp->hw_info.samplerate, bits, channels, "xmame arts"); block = (params->flags & SYSDEP_DSP_O_NONBLOCK) ? 0 : 1; result = arts_stream_set(priv->stream, ARTS_P_BLOCKING, block); if (result < 0) { fprintf(stderr, "arts_stream_set error: %s\n", arts_error_text(result)); arts_dsp_destroy(dsp); return NULL; } else { if (result != block) { fprintf(stderr, "arts_stream_set ARTS_P_BLOCKING to %d failed\n", block); arts_dsp_destroy(dsp); return NULL; } } /* calculate fragsize & number of frags */ /* fragsize (as power of 2) */ i = 7; if (dsp->hw_info.type & SYSDEP_DSP_16BIT) i++; if (dsp->hw_info.type & SYSDEP_DSP_STEREO) i++; i += dsp->hw_info.samplerate / 22050; /* number of frags */ j = ((dsp->hw_info.samplerate * arts_dsp_bytes_per_sample[dsp->hw_info.type] * params->bufsize) / (0x01 << i)) + 1; arts_stream_set(priv->stream, ARTS_P_BUFFER_SIZE, (0x01<<i)*j); #ifdef ARTS_DEBUG /* print some info messages ;) */ fprintf(stderr, "info: aRts buffer size : %d\n", arts_stream_get(priv->stream, ARTS_P_BUFFER_SIZE)); fprintf(stderr, "info: aRts buffer time : %d\n", arts_stream_get(priv->stream, ARTS_P_BUFFER_TIME)); fprintf(stderr, "info: aRts server latency : %d\n", arts_stream_get(priv->stream, ARTS_P_SERVER_LATENCY)); fprintf(stderr, "info: aRts total latency : %d\n", arts_stream_get(priv->stream, ARTS_P_TOTAL_LATENCY)); fprintf(stderr, "info: aRts blocking : %s\n", arts_stream_get(priv->stream, ARTS_P_BLOCKING) ? "yes" : "no"); #endif /* ifdef ARTS_DEBUG */ return dsp; }