sox源码分析:sox_find_effect()

sox_find_effect()主要是根据传入的效果器名字从effects.h文件中定义的效果器中进行遍历查找,最终目的是为了初始化结构体sox_effect_handler_t,关联一系列具体的处理接口函数。以norm为例进行说明。

sox_find_effect()函数调用关系

在这里插入图片描述

关键结构体

/**
Client API:
Effect handler information.
*/
struct sox_effect_handler_t {
    
    
  char const * name;  /**< Effect name */
  char const * usage; /**< Short explanation of parameters accepted by effect */
  unsigned int flags; /**< Combination of SOX_EFF_* flags */
  sox_effect_handler_getopts getopts; /**< Called to parse command-line arguments (called once per effect). */
  sox_effect_handler_start start;     /**< Called to initialize effect (called once per flow). */
  sox_effect_handler_flow flow;       /**< Called to process samples. */
  sox_effect_handler_drain drain;     /**< Called to finish getting output after input is complete. */
  sox_effect_handler_stop stop;       /**< Called to shut down effect (called once per flow). */
  sox_effect_handler_kill kill;       /**< Called to shut down effect (called once per effect). */
  size_t       priv_size;             /**< Size of private data SoX should pre-allocate for effect */
};

关键结构体sox_effect_handler_t 贯穿整个处理过程,主要是定义了一系列操作函数指针,主要通过名字区分不同的处理。

测试代码

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 比较两个字符串是否相同 */
int lsx_strcasecmp(const char * s1, const char * s2)
{
    
    
#if defined(HAVE_STRCASECMP)
  return strcasecmp(s1, s2);
#elif defined(_MSC_VER)
  return _stricmp(s1, s2);
#else
  while (*s1 && (toupper(*s1) == toupper(*s2)))
    s1++, s2++;
  return toupper(*s1) - toupper(*s2);
#endif
}


#ifdef __GNUC__
#define LSX_API  __attribute__ ((cdecl)) /* libSoX function */
#elif _MSC_VER
#define LSX_API  __cdecl /* libSoX function */
#else
#define LSX_API /* libSoX function */
#endif

#define strcasecmp(s1, s2) lsx_strcasecmp((s1), (s2))

/* 定义相应的操作函数接口指针 */
struct sox_effect_handler_t {
    
    
  char const * name;  /**< Effect name */
  char const * usage; /**< Short explanation of parameters accepted by effect */
  // unsigned int flags; /**< Combination of SOX_EFF_* flags */
  // sox_effect_handler_getopts getopts; /**< Called to parse command-line arguments (called once per effect). */
  // sox_effect_handler_start start;     /**< Called to initialize effect (called once per flow). */
  // sox_effect_handler_flow flow;       /**< Called to process samples. */
  // sox_effect_handler_drain drain;     /**< Called to finish getting output after input is complete. */
  // sox_effect_handler_stop stop;       /**< Called to shut down effect (called once per flow). */
  // sox_effect_handler_kill kill;       /**< Called to shut down effect (called once per effect). */
  // size_t       priv_size;             /**< Size of private data SoX should pre-allocate for effect */
};

typedef struct sox_effect_handler_t sox_effect_handler_t;

typedef sox_effect_handler_t const * (LSX_API *sox_effect_fn_t)(void);

void *lsx_realloc(void *ptr, size_t newsize)
{
    
    
  if (ptr && newsize == 0) {
    
    
    free(ptr);
    return NULL;
  }

  if ((ptr = realloc(ptr, newsize)) == NULL) {
    
    
    printf("out of memory");
    exit(2);
  }

  return ptr;
}

#define lsx_malloc(size) lsx_realloc(NULL, (size))

/* 帮助信息解析 */
char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n)
{
    
    
  if (!*usage) {
    
    
    size_t i, len;
    for (len = i = 0; i < n; len += strlen(lines[i++]) + 1);
    *usage = lsx_malloc(len); /* FIXME: this memory will never be freed */
    strcpy(*usage, lines[0]);
    for (i = 1; i < n; ++i) {
    
    
      strcat(*usage, "\n");
      strcat(*usage, lines[i]);
    }
  }
  return *usage;
}

#define array_length(a) (sizeof(a)/sizeof(a[0]))

sox_effect_handler_t const * lsx_gain_effect_fn(void)
{
    
    
  static sox_effect_handler_t handler = {
    
    
    "gain", 
  //   NULL, SOX_EFF_GAIN,
  //   create, start, flow, drain, stop, NULL, sizeof(priv_t)
  };
  static char const * lines[] = {
    
    
    "[-e|-b|-B|-r] [-n] [-l|-h] [gain-dB]",
    "-e\t Equalise channels: peak to that with max peak;",
    "-B\t Balance channels: rms to that with max rms; no clip protection",
    "-b\t Balance channels: rms to that with max rms; clip protection",
    "\t   Note -Bn = -bn",
    "-r\t Reclaim headroom (as much as possible without clipping); see -h",
    "-n\t Norm file to 0dBfs(output precision); gain-dB, if present, usually <0",
    "-l\t Use simple limiter",
    "-h\t Apply attenuation for headroom for subsequent effects; gain-dB, if",
    "\t   present, is subject to reclaim by a subsequent gain -r",
    "gain-dB\t Apply gain in dB",
  };
  static char * usage;
  handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));
  return &handler;
}

/* norm效果器对应的操作函数接口 */
sox_effect_handler_t const * lsx_norm_effect_fn(void)
{
    
    
  static sox_effect_handler_t handler;
  handler = *lsx_gain_effect_fn();    // norm实际处理的是增益,关联增益效果器操作函数接口lsx_gain_effect_fn
  handler.name = "norm";
  handler.usage = "[level]";
  // handler.getopts = norm_getopts;
  return &handler;
}


/*----------------------------- Effects library ------------------------------*/

static sox_effect_fn_t s_sox_effect_fns[] = {
    
    
#define EFFECT(f) lsx_##f##_effect_fn,    //名字
#include "effects.h"
#undef EFFECT
  NULL
};

const sox_effect_fn_t*
sox_get_effect_fns(void)
{
    
    
    return s_sox_effect_fns;
}

/* Find a named effect in the effects library */
/* 根据传入的效果器名字从effects.h文件中定义的效果器中进行遍历查找获取对应的操作函数接口 */
sox_effect_handler_t const * sox_find_effect(char const * name)
{
    
    
  int e;
  sox_effect_fn_t const * fns = sox_get_effect_fns();  // 解析effects.h中的效果器,获取对应效果器的操作函数接口
  for (e = 0; fns[e]; ++e) {
    
    
    const sox_effect_handler_t *eh = fns[e] ();
    if (eh && eh->name && strcasecmp(eh->name, name) == 0) {
    
        // 比较名字
		printf("%s, %s\n", name, eh->name);
        printf("%s\n", eh->usage);
        return eh;                 /* Found it. */
    }
  }
  return NULL;
}

int main()
{
    
    
	sox_find_effect("norm");
}

猜你喜欢

转载自blog.csdn.net/liang_zhaocong/article/details/123395552