/* Initialize voice thread data that must be valid upon starting and the * setup the DSP parameters */ static void voice_data_init(struct voice_thread_data *td) { td->state = TSTATE_STOPPED; td->dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, CODEC_IDX_VOICE); dsp_configure(td->dsp, DSP_RESET, 0); dsp_configure(td->dsp, DSP_SET_FREQUENCY, VOICE_SAMPLE_RATE); dsp_configure(td->dsp, DSP_SET_SAMPLE_DEPTH, VOICE_SAMPLE_DEPTH); dsp_configure(td->dsp, DSP_SET_STEREO_MODE, STEREO_MONO); }
/* Initialize voice thread data that must be valid upon starting and the * setup the DSP parameters */ static void voice_data_init(struct voice_thread_data *td) { td->dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, CODEC_IDX_VOICE); dsp_configure(td->dsp, DSP_RESET, 0); dsp_configure(td->dsp, DSP_SET_FREQUENCY, VOICE_SAMPLE_RATE); dsp_configure(td->dsp, DSP_SET_SAMPLE_DEPTH, VOICE_SAMPLE_DEPTH); dsp_configure(td->dsp, DSP_SET_STEREO_MODE, STEREO_MONO); mixer_channel_set_amplitude(PCM_MIXER_CHAN_VOICE, MIX_AMP_UNITY); }
static void codec_configure_callback(int setting, intptr_t value) { if (!dsp_configure(ci.dsp, setting, value)) { logf("Illegal key: %d", setting); } }
/* Handle Q_CODEC_LOAD */ static void load_codec(const struct codec_load_info *ev_data) { int status = CODEC_ERROR; /* Save a local copy so we can let the audio thread go ASAP */ struct codec_load_info data = *ev_data; bool const encoder = type_is_encoder(data.afmt); if (codec_type != AFMT_UNKNOWN) { /* Must have unloaded it first */ logf("a codec is already loaded"); if (data.hid >= 0) bufclose(data.hid); return; } trigger_cpu_boost(); if (!encoder) { /* Do this now because codec may set some things up at load time */ dsp_configure(ci.dsp, DSP_RESET, 0); } if (data.hid >= 0) { /* First try buffer load */ status = codec_load_buf(data.hid, &ci); bufclose(data.hid); } if (status < 0) { /* Either not a valid handle or the buffer method failed */ const char *codec_fn = get_codec_filename(data.afmt); if (codec_fn) { #ifdef HAVE_IO_PRIORITY buf_back_off_storage(true); #endif status = codec_load_file(codec_fn, &ci); #ifdef HAVE_IO_PRIORITY buf_back_off_storage(false); #endif } } if (status >= 0) { codec_type = data.afmt; codec_queue_ack(Q_CODEC_LOAD); return; } /* Failed - get rid of it */ unload_codec(); }
static void ci_configure(int setting, intptr_t value) { if (use_dsp) { dsp_configure(ci.dsp, setting, value); } else { if (setting == DSP_SET_FREQUENCY || setting == DSP_SET_FREQUENCY) format.freq = value; else if (setting == DSP_SET_SAMPLE_DEPTH) format.depth = value; else if (setting == DSP_SET_STEREO_MODE) { format.stereo_mode = value; format.channels = (value == STEREO_MONO) ? 1 : 2; } } }
/* Initialize codec API */ void codec_init_codec_api(void) { ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, CODEC_IDX_AUDIO); ci.codec_get_buffer = codec_get_buffer_callback; ci.pcmbuf_insert = codec_pcmbuf_insert_callback; ci.set_elapsed = audio_codec_update_elapsed; ci.read_filebuf = codec_filebuf_callback; ci.request_buffer = codec_request_buffer_callback; ci.advance_buffer = codec_advance_buffer_callback; ci.seek_buffer = codec_seek_buffer_callback; ci.seek_complete = codec_seek_complete_callback; ci.set_offset = audio_codec_update_offset; ci.configure = codec_configure_callback; ci.get_command = codec_get_command_callback; }
/* Initialize codec API */ void codec_init_codec_api(void) { ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP, CODEC_IDX_AUDIO); ci.codec_get_buffer = codec_get_buffer; ci.pcmbuf_insert = codec_pcmbuf_insert_callback; ci.set_elapsed = codec_set_elapsed_callback; ci.read_filebuf = codec_filebuf_callback; ci.request_buffer = codec_request_buffer_callback; ci.advance_buffer = codec_advance_buffer_callback; ci.advance_buffer_loc = codec_advance_buffer_loc_callback; ci.seek_buffer = codec_seek_buffer_callback; ci.seek_complete = codec_seek_complete_callback; ci.request_next_track = codec_request_next_track_callback; ci.discard_codec = codec_discard_codec_callback; ci.set_offset = codec_set_offset_callback; ci.configure = codec_configure_callback; }
static void codec_seek_complete_callback(void) { logf("seek_complete"); /* Clear DSP */ dsp_configure(ci.dsp, DSP_FLUSH, 0); /* Post notification to audio thread */ LOGFQUEUE("audio > Q_AUDIO_CODEC_SEEK_COMPLETE"); audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE, 0); /* Wait for urgent or go message */ do { queue_wait(&codec_queue, NULL); } while (codec_check_queue__have_msg() == 0); }
static void codec_seek_complete_callback(void) { logf("seek_complete"); /* If seeking-while-playing, pcm_is_paused() is true. * If seeking-while-paused, audio_status PAUSE is true. * A seamless seek skips this section. */ bool audio_paused = audio_status() & AUDIO_STATUS_PAUSE; if (pcm_is_paused() || audio_paused) { /* Clear the buffer */ pcmbuf_play_stop(); dsp_configure(ci.dsp, DSP_FLUSH, 0); /* If seeking-while-playing, resume pcm playback */ if (!audio_paused) pcmbuf_pause(false); } ci.seek_time = 0; }
static void decode_file(const char *input_fn) { /* Initialize DSP before any sort of interaction */ dsp_init(); /* Set up global settings */ memset(&global_settings, 0, sizeof(global_settings)); global_settings.timestretch_enabled = true; dsp_timestretch_enable(true); /* Open file */ if (!strcmp(input_fn, "-")) { input_fd = STDIN_FILENO; } else { input_fd = open(input_fn, O_RDONLY); if (input_fd == -1) { perror(input_fn); exit(1); } } /* Set up ci */ struct mp3entry id3; if (!get_metadata(&id3, input_fd, input_fn)) { fprintf(stderr, "error: metadata parsing failed\n"); exit(1); } print_mp3entry(&id3, stderr); ci.filesize = filesize(input_fd); ci.id3 = &id3; if (use_dsp) { ci.dsp = dsp_get_config(CODEC_IDX_AUDIO); dsp_configure(ci.dsp, DSP_SET_OUT_FREQUENCY, DSP_OUT_DEFAULT_HZ); dsp_configure(ci.dsp, DSP_RESET, 0); dsp_dither_enable(false); } perform_config(); /* Load codec */ char str[MAX_PATH]; snprintf(str, sizeof(str), CODECDIR"/%s.codec", audio_formats[id3.codectype].codec_root_fn); debugf("Loading %s\n", str); void *dlcodec = dlopen(str, RTLD_NOW); if (!dlcodec) { fprintf(stderr, "error: dlopen failed: %s\n", dlerror()); exit(1); } struct codec_header *c_hdr = NULL; c_hdr = dlsym(dlcodec, "__header"); if (c_hdr->lc_hdr.magic != CODEC_MAGIC) { fprintf(stderr, "error: %s invalid: incorrect magic\n", str); exit(1); } if (c_hdr->lc_hdr.target_id != TARGET_ID) { fprintf(stderr, "error: %s invalid: incorrect target id\n", str); exit(1); } if (c_hdr->lc_hdr.api_version != CODEC_API_VERSION) { fprintf(stderr, "error: %s invalid: incorrect API version\n", str); exit(1); } /* Run the codec */ *c_hdr->api = &ci; if (c_hdr->entry_point(CODEC_LOAD) != CODEC_OK) { fprintf(stderr, "error: codec returned error from codec_main\n"); exit(1); } if (c_hdr->run_proc() != CODEC_OK) { fprintf(stderr, "error: codec error\n"); } c_hdr->entry_point(CODEC_UNLOAD); /* Close */ dlclose(dlcodec); if (input_fd != STDIN_FILENO) close(input_fd); }