📄 af.c
字号:
// Check if this is the first call if(!s->first){ // Add all filters in the list (if there are any) if(!s->cfg.list){ // To make automatic format conversion work if(!af_append(s,s->first,"dummy")) return -1; } else{ while(s->cfg.list[i]){ if(!af_append(s,s->last,s->cfg.list[i++])) return -1; } } } // Init filters if(AF_OK != af_reinit(s,s->first)) return -1; // If force_output isn't set do not compensate for output format if(!force_output){ memcpy(&s->output, s->last->data, sizeof(af_data_t)); return 0; } // Check output format if((AF_INIT_TYPE_MASK & s->cfg.force) != AF_INIT_FORCE){ af_instance_t* af = NULL; // New filter // Check output frequency if not OK fix with resample if(s->last->data->rate!=s->output.rate){ // try to find a filter that can change samplrate af = af_control_any_rev(s, AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET, &(s->output.rate)); if (!af) { char *resampler = "resample";#ifdef USE_LIBAVCODEC if ((AF_INIT_TYPE_MASK & s->cfg.force) == AF_INIT_SLOW) resampler = "lavcresample";#endif if((AF_INIT_TYPE_MASK & s->cfg.force) == AF_INIT_SLOW){ if(!strcmp(s->first->info->name,"format")) af = af_append(s,s->first,resampler); else af = af_prepend(s,s->first,resampler); } else{ if(!strcmp(s->last->info->name,"format")) af = af_prepend(s,s->last,resampler); else af = af_append(s,s->last,resampler); } // Init the new filter if(!af || (AF_OK != af->control(af,AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET, &(s->output.rate)))) return -1; // Use lin int if the user wants fast if ((AF_INIT_TYPE_MASK & s->cfg.force) == AF_INIT_FAST) { char args[32]; sprintf(args, "%d", s->output.rate);#ifdef USE_LIBAVCODEC if (strcmp(resampler, "lavcresample") == 0) strcat(args, ":1"); else#endif strcat(args, ":0:0"); af->control(af, AF_CONTROL_COMMAND_LINE, args); } } if(AF_OK != af_reinit(s,af)) return -1; } // Check number of output channels fix if not OK // If needed always inserted last -> easy to screw up other filters if(s->last->data->nch!=s->output.nch){ if(!strcmp(s->last->info->name,"format")) af = af_prepend(s,s->last,"channels"); else af = af_append(s,s->last,"channels"); // Init the new filter if(!af || (AF_OK != af->control(af,AF_CONTROL_CHANNELS,&(s->output.nch)))) return -1; if(AF_OK != af_reinit(s,af)) return -1; } // Check output format fix if not OK if(s->last->data->format != s->output.format){ if(strcmp(s->last->info->name,"format")) af = af_append(s,s->last,"format"); else af = s->last; // Init the new filter s->output.format |= af_bits2fmt(s->output.bps*8); if(!af || (AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT,&(s->output.format)))) return -1; if(AF_OK != af_reinit(s,af)) return -1; } // Re init again just in case if(AF_OK != af_reinit(s,s->first)) return -1; if((s->last->data->format != s->output.format) || (s->last->data->nch != s->output.nch) || (s->last->data->rate != s->output.rate)) { // Something is stuffed audio out will not work af_msg(AF_MSG_ERROR,"[libaf] Unable to setup filter system can not" " meet sound-card demands, please send bugreport. \n"); af_uninit(s); return -1; } } return 0;}/* Add filter during execution. This function adds the filter "name" to the stream s. The filter will be inserted somewhere nice in the list of filters. The return value is a pointer to the new filter, If the filter couldn't be added the return value is NULL. */af_instance_t* af_add(af_stream_t* s, char* name){ af_instance_t* new; // Sanity check if(!s || !s->first || !name) return NULL; // Insert the filter somwhere nice if(!strcmp(s->first->info->name,"format")) new = af_append(s, s->first, name); else new = af_prepend(s, s->first, name); if(!new) return NULL; // Reinitalize the filter list if(AF_OK != af_reinit(s, s->first)){ free(new); return NULL; } return new;}// Filter data chunk through the filters in the listaf_data_t* af_play(af_stream_t* s, af_data_t* data){ af_instance_t* af=s->first; // Iterate through all filters do{ data=af->play(af,data); af=af->next; }while(af); return data;}/* Helper function used to calculate the exact buffer length needed when buffers are resized. The returned length is >= than what is needed */inline int af_lencalc(frac_t mul, af_data_t* d){ register int t = d->bps*d->nch; return t*(((d->len/t)*mul.n)/mul.d + 1);}/* Calculate how long the output from the filters will be given the input length "len". The calculated length is >= the actual length. */int af_outputlen(af_stream_t* s, int len){ int t = s->input.bps*s->input.nch; af_instance_t* af=s->first; frac_t mul = {1,1}; // Iterate through all filters do{ af_frac_mul(&mul, &af->mul); af=af->next; }while(af); return t * (((len/t)*mul.n + 1)/mul.d);}/* Calculate how long the input to the filters should be to produce a certain output length, i.e. the return value of this function is the input length required to produce the output length "len". The calculated length is <= the actual length */int af_inputlen(af_stream_t* s, int len){ int t = s->input.bps*s->input.nch; af_instance_t* af=s->first; frac_t mul = {1,1}; // Iterate through all filters do{ af_frac_mul(&mul, &af->mul); af=af->next; }while(af); return t * (((len/t) * mul.d - 1)/mul.n);}/* Calculate how long the input IN to the filters should be to produce a certain output length OUT but with the following three constraints: 1. IN <= max_insize, where max_insize is the maximum possible input block length 2. OUT <= max_outsize, where max_outsize is the maximum possible output block length 3. If possible OUT >= len. Return -1 in case of error */ int af_calc_insize_constrained(af_stream_t* s, int len, int max_outsize,int max_insize){ int t = s->input.bps*s->input.nch; int in = 0; int out = 0; af_instance_t* af=s->first; frac_t mul = {1,1}; // Iterate through all filters and calculate total multiplication factor do{ af_frac_mul(&mul, &af->mul); af=af->next; }while(af); // Sanity check if(!mul.n || !mul.d) return -1; in = t * (((len/t) * mul.d - 1)/mul.n); if(in>max_insize) in=t*(max_insize/t); // Try to meet constraint nr 3. while((out=t * (((in/t+1)*mul.n - 1)/mul.d)) <= max_outsize && in<=max_insize){ if( (t * (((in/t)*mul.n))/mul.d) >= len) return in; in+=t; } // Could no meet constraint nr 3. while(out > max_outsize || in > max_insize){ in-=t; if(in<t) return -1; // Input parameters are probably incorrect out = t * (((in/t)*mul.n + 1)/mul.d); } return in;}/* Calculate the total delay [ms] caused by the filters */double af_calc_delay(af_stream_t* s){ af_instance_t* af=s->first; register double delay = 0.0; // Iterate through all filters while(af){ delay += af->delay; af=af->next; } return delay;}/* Helper function called by the macro with the same name this function should not be called directly */inline int af_resize_local_buffer(af_instance_t* af, af_data_t* data){ // Calculate new length register int len = af_lencalc(af->mul,data); af_msg(AF_MSG_VERBOSE,"[libaf] Reallocating memory in module %s, " "old len = %i, new len = %i\n",af->info->name,af->data->len,len); // If there is a buffer free it if(af->data->audio) free(af->data->audio); // Create new buffer and check that it is OK af->data->audio = malloc(len); if(!af->data->audio){ af_msg(AF_MSG_FATAL,"[libaf] Could not allocate memory \n"); return AF_ERROR; } af->data->len=len; return AF_OK;}/** * \brief send control to all filters, starting with the last, until * one responds with AF_OK * \return The instance that accepted the command or NULL if none did. */af_instance_t *af_control_any_rev (af_stream_t* s, int cmd, void* arg) { int res = AF_UNKNOWN; af_instance_t* filt = s->last; while (filt) { res = filt->control(filt, cmd, arg); if (res == AF_OK) return filt; filt = filt->prev; } return NULL;}/** * \brief calculate greatest common divisior of a and b. * Extended for negative and 0 values. If both are 0 the result is 1. * The sign of the result will be so that it has the same sign as b. */int af_gcd(register int a, register int b) { int b_org = b; while (b != 0) { a %= b; if (a == 0) break; b %= a; } // the result is either in a or b. As the other one is 0 just add them. a += b; if (!a) return 1; if (a * b_org < 0) return -a; return a;}/** * \brief cancel down a fraction f */void af_frac_cancel(frac_t *f) { int gcd = af_gcd(f->n, f->d); f->n /= gcd; f->d /= gcd;}/** * \brief multiply out by in and store result in out. * the resulting fraction wil be cancelled down * if in and out were. */void af_frac_mul(frac_t *out, const frac_t *in) { int gcd1 = af_gcd(out->n, in->d); int gcd2 = af_gcd(in->n, out->d); out->n = (out->n / gcd1) * (in->n / gcd2); out->d = (out->d / gcd2) * (in->d / gcd1);}void af_help (void) { int i = 0; af_msg(AF_MSG_INFO, "Available audio filters:\n"); while (filter_list[i]) { if (filter_list[i]->comment && filter_list[i]->comment[0]) af_msg(AF_MSG_INFO, " %-15s: %s (%s)\n", filter_list[i]->name, filter_list[i]->info, filter_list[i]->comment); else af_msg(AF_MSG_INFO, " %-15s: %s\n", filter_list[i]->name, filter_list[i]->info); i++; }}void af_fix_parameters(af_data_t *data){ data->bps = af_fmt2bits(data->format)/8;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -