`
lobin
  • 浏览: 425936 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

C: Linux C 编程 - SDL+mpg123音频处理

 
阅读更多

采样率

 

采样率可以通过mpg123_rates函数获取mpg123支持哪些采样率:

MPG123_EXPORT void mpg123_rates(const long **list, size_t *number);

 

通道数

定义:

/** They can be combined into one number (3) to indicate mono and stereo... */

enum mpg123_channelcount

{

MPG123_MONO   = 1 /**< mono */

,MPG123_STEREO = 2 /**< stereo */

};

 

编码(格式)

 

编码(格式)可以通过mpg123_encodings函数获取mpg123支持哪些编码(格式)

MPG123_EXPORT void mpg123_encodings(const int **list, size_t *number);

 

获取音频格式:

MPG123_EXPORT int mpg123_getformat( mpg123_handle *mh

, long *rate, int *channels, int *encoding );
参数rate表示采样率

参数channels表示通道数

参数encoding表示编码(格式)

 

播放mp3格式的音频

#include<stdio.h>
#include<string.h>
#include<SDL_audio.h>
#include<mpg123.h>

#define CHUNK_SIZE 16384

#define INIT_CHUNK_LIST(chunk_list) \
{                                   \
  chunk_list.head = NULL;           \
  chunk_list.tail = NULL;           \
  chunk_list.ptr = NULL;            \
  chunk_list.ptr_pos = 0;           \
}

typedef struct chunk
{
  unsigned char data[CHUNK_SIZE];
  int size;
  struct chunk *next;
} chunk_t;

typedef struct 
{
  struct chunk *head;
  struct chunk *tail;

  struct chunk *ptr;
  int ptr_pos;
} chunk_list_t;


#define BUFFER_SIZE 16384

chunk_list_t chunk_list;

struct chunk* alloc_chunk() 
{
  struct chunk *ptr = (struct chunk *) malloc(sizeof(struct chunk));
  memset(ptr, 0, sizeof(struct chunk));
  return ptr;
}

int chunk_list_empty(chunk_list_t *chunk_list)
{
  return chunk_list->head == NULL && chunk_list->tail == NULL;
}

void chunk_list_add(chunk_list_t *chunk_list, chunk_t *chunk)
{
  if (chunk_list_empty(chunk_list))
  {
    chunk_list->head = chunk;
    chunk_list->tail = chunk;
  }
  else
  {
    chunk_list->tail->next = chunk;
    chunk_list->tail = chunk;
  }
}

void callback_on_take_sample(void *unused, Uint8 *stream, int len)
{
  chunk_list_t* chunk_list = (chunk_list_t *) (unused);
  chunk_t *ptr;
next:
  ptr = chunk_list->ptr;
  if (ptr == NULL)
  {
    SDL_PauseAudio(1);
    return;
  }

  int amount = ptr->size - chunk_list->ptr_pos;
  if (amount > len) 
  {
    amount = len;
  }

  if (amount <= 0)
  {
    chunk_list->ptr = ptr->next;
    chunk_list->ptr_pos = 0;
    goto next;
  }

  printf("audio: len= %u, pos= %u. audio buffer: @%p, len= %d, amount= %d\n", ptr->size, chunk_list->ptr_pos, stream, len, amount);
  SDL_memcpy(stream, ptr->data + chunk_list->ptr_pos, amount);
  chunk_list->ptr_pos += amount;
}

void memdump(unsigned char* in, size_t size)
{
  int i;
  for (i = 0; i < size; i++)
  {
    fprintf(stdout, "%.2X ", in[i]);
  }
  fprintf(stdout, "\n");
}

int read_chunk_internal_handle(mpg123_handle *handle, chunk_t* chunk, int *state)
{
  int result = 0;
  size_t nbytes;

  while(chunk->size < CHUNK_SIZE) 
  {
    result = mpg123_decode(handle, NULL, 0, chunk->data + chunk->size, CHUNK_SIZE - chunk->size, &nbytes);
    if (result == MPG123_ERR)
    {
      fprintf(stderr, "decode err: %d\n", result);
      return 1;
    }
    fprintf(stdout, "decode: result=%d, actually decoded bytes=%u\n", result, nbytes);

    if (nbytes > 0)
    {
      chunk->size += nbytes;
    }

    if (result == MPG123_NEW_FORMAT)
    {
      *state = result;
    }
    if (result == MPG123_NEED_MORE)
    {
      break;
    }
    if (result == MPG123_DONE)
    {
      *state = result;
      break;
    }
  }
  return 0;
}

int read_chunk(FILE *fp, mpg123_handle *handle, chunk_t* chunk, int *state)
{
  int result = 0;
  size_t nbytes;

  //fprintf(stdout, "reading from internal handle...\n");
  result = read_chunk_internal_handle(handle, chunk, state);
  if (result)
  {
    return result;
  }

  //fprintf(stdout, "reading from fp...\n");
  while(chunk->size < CHUNK_SIZE) 
  {
    char buf[BUFFER_SIZE];

    nbytes = fread(buf, 1, sizeof(buf), fp);
    result = ferror(fp);
    if (result)
    {
      fprintf(stderr, "read err: %d\n", result);
      return 1;
    }
    if (feof(fp))
    {
      return -1;
    }
    fprintf(stdout, "read: %d bytes\n", nbytes);

    result = mpg123_decode(handle, buf, nbytes, chunk->data + chunk->size, CHUNK_SIZE - chunk->size, &nbytes);
    if (result == MPG123_ERR)
    {
      fprintf(stderr, "decode err: %d\n", result);
      return 1;
    }
    fprintf(stdout, "decode: result=%d, actually decoded bytes=%u\n", result, nbytes);

    if (nbytes > 0)
    {
      chunk->size += nbytes;
    }

    if (result == MPG123_NEW_FORMAT)
    {
      *state = result;
    }
    if (result == MPG123_DONE)
    {
      break;
    }
  }
  return 0;
}

// .\mpg123_test h:\\yuganqingwuguan.mp3
int main(int argc, char** argv)
{
  int result = 0;
  char *filename;
  FILE *fp;

  
  chunk_t *chunk;

  const char **decoders;
  const char **supported_decoders;
  mpg123_handle *handle;

  SDL_AudioSpec audio_spec_desired;
  SDL_AudioSpec audio_spec_obtained;

  int i;

  if (argc != 2)
  {
    fprintf(stderr, "invalid args\n");
    return 1;
  }
  filename = argv[1];

  INIT_CHUNK_LIST(chunk_list);

  result = mpg123_init();
  if (result != MPG123_OK)
  {
    fprintf(stderr, "init err: %d\n", result);
    return 1;
  }

  fprintf(stdout, "available decoder list: \n");
  decoders = mpg123_decoders();
  for (i = 0; decoders[i] != NULL; i++)
  {
    fprintf(stdout, "\t%d: %s\n", i, decoders[i]);
  }

  supported_decoders = mpg123_supported_decoders();
  fprintf(stdout, "decoders supported: \n");
  for (i = 0; supported_decoders[i] != NULL; i++)
  {
    fprintf(stdout, "\t%d: %s\n", i, supported_decoders[i]);
  }

  handle = mpg123_new(NULL, &result);
  if (handle == NULL)
  {
    fprintf(stderr, "new err: %d\n", result);
  }

  fprintf(stdout, "current decoder: %s\n", mpg123_current_decoder(handle));

  result = mpg123_open_feed(handle);
  if (result != MPG123_OK)
  {
    fprintf(stderr, "open feed err: %d\n", result);
    return 1;
  }

  fp = fopen(filename, "rb");
  if (fp == NULL)
  {
    fprintf(stderr, "open err: %s\n", filename);
    return 1;
  }

  i = 0;
  while (result != MPG123_DONE)
  {
    int ret = 0;
    chunk = alloc_chunk();
    ret = read_chunk(fp, handle, chunk, &result);
    if (ret)
    {
      if (ret == -1)
      {
        break;
      }
      fprintf(stderr, "read chunk err\n");
      return 1;
    }
    i++;
    fprintf(stdout, "%d chunk readed...\n", i);
    chunk_list_add(&chunk_list, chunk);
    if (result == MPG123_NEW_FORMAT)
    {
      long rate;
      int channels;
      int encoding;

      result = mpg123_getformat(handle, &rate, &channels, &encoding);
      if (result != MPG123_OK)
      {
        fprintf(stderr, "get format err: %d\n", result);
        return 1;
      }
      fprintf(stdout, "format: rate=%ld, channels=%d, encoding=%d\n", rate, channels, encoding);

      chunk_list.ptr = chunk_list.head;

      audio_spec_desired.freq = rate; 
      audio_spec_desired.format = AUDIO_S16; 
      audio_spec_desired.samples = 4096; 
      audio_spec_desired.callback = callback_on_take_sample; 
      audio_spec_desired.userdata = &chunk_list; 
      audio_spec_desired.channels = channels;

      if (SDL_OpenAudio(&audio_spec_desired, &audio_spec_obtained) < 0)
      {
        fprintf(stderr, "open audio err: %s\n", SDL_GetError());
        return -1;
      }
    }
  }
  SDL_PauseAudio(0);
  printf("playing...%s\n", filename);

  while ((SDL_GetAudioStatus() == SDL_AUDIO_PLAYING)) 
  {
    SDL_Delay(1000);
  }
  printf("played!\n");

  SDL_CloseAudio();
  SDL_Quit();
}

编译

这里一次性完成编译链接。编译的时候注意通过“-I”指定头文件目录,在链接的时候通过“-L”指定要链接的静态库文件目录,以及通过“-l”指定要链接的静态库。

 

gcc -I/usr/local/SDL2-2.0.7/include/SDL2 -L/usr/local/lib -L/usr/local/SDL2-2.0.7/lib  mpg123_test.c -o mpg123_test -lSDL2 -lmpg123

 

运行

如果是在Cygwin下,在运行之前SDL2.dll、cygmpg123-0.dll拷贝到程序目录下:

>cp -rf d:\sbin\usr\local\sdl\bin\SDL2.dll .

>cp -rf D:\sbin\usr\local\bin\cygmpg123-0.dll .

 

>.\mpg123_test h:\\yuganqingwuguan.mp3

0
0
分享到:
评论

相关推荐

    海思hi3559a编译freetype-2.10.1+SDL2-2.0.12+SDL2_ttf-2.0.15 +测试代码

    hi3559a交叉编译freetype-2.10.1+SDL2-2.0.12+SDL2_ttf-2.0.15 +测试代码。包括库文件,每个包下面有个build.sh脚本,分别执行脚本即可。(这是linux下的压缩包,其他系统无法解压)

    mpg123 linux MP3播放器源码

    mpg123是优秀的mp3播放器,这是源码包,在嵌入式开发声卡中,可以利用该源码进行交叉编译实现MP3播放。

    开源项目-veandco-go-sdl2.zip

    此项目的最新版本为v0.3,它提供了Go编程语言对Simple DirectMedia Layer(SDL2)的绑定,允许Go开发者利用SDL2的强大功能进行游戏开发、多媒体处理和其他图形用户界面相关的应用。 SDL2是一个跨平台的开发库,广泛...

    FFmpeg再学习 -- FFmpeg+SDL+MFC实现图形界面视频播放器-附件资源

    FFmpeg再学习 -- FFmpeg+SDL+MFC实现图形界面视频播放器-附件资源

    SDL+FFmpeg的音频demo

    SDL音频部分包括音频缓冲区管理和混合,支持多种音频格式,并且提供了一套事件驱动的模型来处理音频播放。 **FFmpeg详解** FFmpeg是一个强大的开源多媒体框架,用于处理音频、视频、图像等多种格式的数据。它包含了...

    linux sdl 库和头文件

    Linux下的Simple DirectMedia Layer(SDL)是一个开源的跨平台开发库,主要用于处理多媒体、图形界面、游戏开发等任务。SDL库提供了丰富的功能,包括硬件加速的2D图形、音频输入和输出、键盘和鼠标事件处理、游戏...

    sdl+ffmpeg视频播放器

    首先,SDL是一个低级别的多媒体库,它为开发者提供了处理图形、音频、输入设备等的能力,特别适合用于游戏开发和多媒体应用。它的主要特点包括: 1. **图形渲染**:SDL提供了一套API,可以创建窗口、渲染2D图形,并...

    09-SDL音视频渲染实战SDL安装和接口说明

    3. **07linux-sdl-thread**:多线程编程在现代应用中至关重要,特别是在处理音视频时。这部分会讲解如何在SDL中创建和管理线程,以实现并发任务,比如同时播放音频和渲染视频。 4. **08linux-sdl-playyuv**:YUV是...

    C语言案例1:SDL2游戏编程基础之环境准备-配套资源.zip

    在本资源包中,我们主要关注的是C语言与SDL2库结合进行游戏编程的基础知识。SDL2(Simple DirectMedia Layer 2)是一个跨平台的开发库,它为开发者提供了丰富的功能,包括图形渲染、音频处理、事件管理等,是创建2D...

    QT + ffmpeg + sdl音频播放器

    QT + ffmpeg + SDL音频播放器是一种利用开源库组合来实现音频播放的应用程序。在这个项目中,QT是一个跨平台的C++应用程序开发框架,用于构建用户界面;ffmpeg是一个强大的多媒体处理库,负责音频和视频的解码;而...

    ffmpeg+sdl视音频播放器

    ffmpeg+sdl播放器解码视音频,使用ffmpeg-2.5.2+SDL-1.2.15,参考ffmpeg官方例子,欢迎交流 内含10个工程 1.保存为bmp图片 2.解码视频 3.解码视频, 音频 4.分离代码,加入线程(伪同步) 5.视频同步到音频 6.音频同步到...

    sdl的linux源码包SDL2-2.0.2

    **标题与描述解析** 标题"SDL2-2.0.2"指的是...熟悉C/C++编程是必要的,因为这是SDL2主要支持的语言。对于Linux运维人员来说,理解如何在服务器上安装、管理和更新SDL2库,以及解决相关的依赖问题,也是重要的技能。

    tank-sdl-0.3.0.tar.gz_game tank sdl_sdl game sour_tank-sdl _tan

    SDL提供了基本的窗口管理、图像渲染、音频播放和键盘/鼠标输入处理等功能,是许多初学者和专业开发者入门游戏编程的首选库。 在"tank-sdl-0.3.0"源代码中,我们可以学习到以下关键点: 1. **游戏循环**:任何游戏...

    linux下实现ffmpeg+sdl视音频播放

    在Linux环境下,使用FFmpeg和SDL(Simple DirectMedia Layer)框架...这个过程中涉及的知识点包括音视频编码解码原理、多媒体文件格式、流处理技术、图形用户界面编程等,是深入理解多媒体处理和Linux开发的重要实践。

    开源项目-gen2brain-go-sdl2-android-example.zip

    SDL2(Simple DirectMedia Layer 2)是一个跨平台的开发库,用于处理图形、音频、输入设备等多媒体元素。它在游戏开发领域特别受欢迎,因为它的API简洁高效,并且支持多种操作系统,包括Windows、Linux、Mac OS X...

    Go-go-sdl2-Go绑定SimpleDirectMediaLayer

    这个Go绑定使得Go程序员能够利用C语言的SDL2库的强大功能,而无需直接处理C语言的复杂性。 Go-sdl2是Go语言中的一个开源项目,它为Go程序员提供了与SDL2库交互的API。这包括窗口管理、事件处理、图像渲染、音频处理...

    ffmpeg+SDL2实现的音频播放器V2.0(无杂音)

    SDL2(Simple DirectMedia Layer)则是一个跨平台的开发库,用于处理图形用户界面、音频和输入设备,常用于游戏开发和多媒体应用。 在这个"ffmpeg+SDL2实现的音频播放器V2.0(无杂音)"项目中,开发者利用 FFmpeg ...

    06-SDL音视频渲染实战.rar

    - 音频回调函数:开发者可以注册一个回调函数,每当需要填充音频缓冲区时,SDL会自动调用该函数,将处理后的音频数据填入缓冲区。 - 音频格式转换:SDL支持多种音频格式,如果原始音频数据与目标设备不兼容,SDL...

    C-SDL:C语言SDL解析器解释器

    **C-SDL:C语言SDL解析器解释器** C-SDL是一个基于C语言实现的SDL(Simple DirectMedia Layer)解析器和解释器。SDL库是一个跨平台的开发库,主要用于多媒体应用开发,如游戏、图形界面和音频处理。C-SDL项目的目标...

Global site tag (gtag.js) - Google Analytics