// Filter data through filter static af_data_t* play(struct af_instance_s* af, af_data_t* data) { af_data_t* c = data; // Current working data af_data_t* l = af->data; // Local data af_channels_t* s = af->setup; int i; if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) return NULL; // Reset unused channels memset(l->audio,0,(c->len*af->mul.n)/af->mul.d); if(AF_OK == check_routes(s,c->nch,l->nch)) for(i=0;i<s->nr;i++) copy(c->audio,l->audio,c->nch,s->route[i][FR], l->nch,s->route[i][TO],c->len,c->bps); // Set output data c->audio = l->audio; c->len = (c->len*af->mul.n)/af->mul.d; c->nch = l->nch; return c; }
// Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { af_channels_t* s = af->priv; switch(cmd){ case AF_CONTROL_REINIT: ; struct mp_chmap chmap; mp_chmap_set_unknown(&chmap, s->nch); mp_audio_set_channels(af->data, &chmap); // Set default channel assignment if(!s->router){ int i; // Make sure this filter isn't redundant if(af->data->nch == ((struct mp_audio*)arg)->nch) return AF_DETACH; // If mono: fake stereo if(((struct mp_audio*)arg)->nch == 1){ s->nr = MPMIN(af->data->nch,2); for(i=0;i<s->nr;i++){ s->route[i][FR] = 0; s->route[i][TO] = i; } } else{ s->nr = MPMIN(af->data->nch, ((struct mp_audio*)arg)->nch); for(i=0;i<s->nr;i++){ s->route[i][FR] = i; s->route[i][TO] = i; } } } af->data->rate = ((struct mp_audio*)arg)->rate; mp_audio_force_interleaved_format((struct mp_audio*)arg); mp_audio_set_format(af->data, ((struct mp_audio*)arg)->format); return check_routes(af,((struct mp_audio*)arg)->nch,af->data->nch); } return AF_UNKNOWN; }
// Filter data through filter static int filter(struct af_instance* af, struct mp_audio* data, int flags) { struct mp_audio* c = data; // Current working data struct mp_audio* l = af->data; // Local data af_channels_t* s = af->priv; int i; mp_audio_realloc_min(af->data, data->samples); // Reset unused channels memset(l->planes[0],0,mp_audio_psize(c) / c->nch * l->nch); if(AF_OK == check_routes(af,c->nch,l->nch)) for(i=0;i<s->nr;i++) copy(af, c->planes[0],l->planes[0],c->nch,s->route[i][FR], l->nch,s->route[i][TO],mp_audio_psize(c),c->bps); // Set output data c->planes[0] = l->planes[0]; mp_audio_set_channels(c, &l->channels); return 0; }
// Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { af_channels_t* s = af->setup; switch(cmd){ case AF_CONTROL_REINIT: // Set default channel assignment if(!s->router){ int i; // Make sure this filter isn't redundant if(af->data->nch == ((af_data_t*)arg)->nch) return AF_DETACH; // If mono: fake stereo if(((af_data_t*)arg)->nch == 1){ s->nr = min(af->data->nch,2); for(i=0;i<s->nr;i++){ s->route[i][FR] = 0; s->route[i][TO] = i; } } else{ s->nr = min(af->data->nch, ((af_data_t*)arg)->nch); for(i=0;i<s->nr;i++){ s->route[i][FR] = i; s->route[i][TO] = i; } } } af->data->rate = ((af_data_t*)arg)->rate; af->data->format = ((af_data_t*)arg)->format; af->data->bps = ((af_data_t*)arg)->bps; af->mul.n = af->data->nch; af->mul.d = ((af_data_t*)arg)->nch; af_frac_cancel(&af->mul); return check_routes(s,((af_data_t*)arg)->nch,af->data->nch); case AF_CONTROL_COMMAND_LINE:{ int nch = 0; int n = 0; // Check number of channels and number of routing pairs sscanf(arg, "%i:%i%n", &nch, &s->nr, &n); // If router scan commandline for routing pairs if(s->nr){ char* cp = &((char*)arg)[n]; int ch = 0; // Sanity check if((s->nr < 1) || (s->nr > AF_NCH)){ af_msg(AF_MSG_ERROR,"[channels] The number of routing pairs must be" " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); } s->router = 1; // Scan for pairs on commandline while((*cp == ':') && (ch < s->nr)){ sscanf(cp, ":%i:%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n); af_msg(AF_MSG_VERBOSE,"[channels] Routing from channel %i to" " channel %i\n",s->route[ch][FR],s->route[ch][TO]); cp = &cp[n]; ch++; } } if(AF_OK != af->control(af,AF_CONTROL_CHANNELS | AF_CONTROL_SET ,&nch)) return AF_ERROR; return AF_OK; } case AF_CONTROL_CHANNELS | AF_CONTROL_SET: // Reinit must be called after this function has been called // Sanity check if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH){ af_msg(AF_MSG_ERROR,"[channels] The number of output channels must be" " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]); return AF_ERROR; } af->data->nch=((int*)arg)[0]; if(!s->router) af_msg(AF_MSG_VERBOSE,"[channels] Changing number of channels" " to %i\n",af->data->nch); return AF_OK; case AF_CONTROL_CHANNELS | AF_CONTROL_GET: *(int*)arg = af->data->nch; return AF_OK; case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_SET:{ int ch = ((af_control_ext_t*)arg)->ch; int* route = ((af_control_ext_t*)arg)->arg; s->route[ch][FR] = route[FR]; s->route[ch][TO] = route[TO]; return AF_OK; } case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_GET:{ int ch = ((af_control_ext_t*)arg)->ch; int* route = ((af_control_ext_t*)arg)->arg; route[FR] = s->route[ch][FR]; route[TO] = s->route[ch][TO]; return AF_OK; } case AF_CONTROL_CHANNELS_NR | AF_CONTROL_SET: s->nr = *(int*)arg; return AF_OK; case AF_CONTROL_CHANNELS_NR | AF_CONTROL_GET: *(int*)arg = s->nr; return AF_OK; case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_SET: s->router = *(int*)arg; return AF_OK; case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_GET: *(int*)arg = s->router; return AF_OK; } return AF_UNKNOWN; }