混音相关代码来源于doubango,自己做了提取,个人感觉效果还不错
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
typedef int int16_t;
typedef unsigned int uint32_t;
typedef unsigned int tsk_size_t;
#define tsk_null NULL
#define TSK_DEBUG_ERROR(FMT, ...) fprintf(stderr, "***ERROR: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);
#define TSK_DEBUG_INFO(FMT, ...) fprintf(stderr, "***INFO: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);
#define TSK_DEBUG_WARN(FMT, ...) fprintf(stderr, "***WARN: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);
#define TSK_SAFE_FREE(ptr) (void)tsk_free((void**)(&ptr));
//音频包
typedef struct audio_buffer_s {
int16_t* audio;
size_t size;
struct audio_buffer_s* next;
} audio_buffer_t;
void* tsk_calloc(tsk_size_t num, tsk_size_t size)
{
void* ret = tsk_null;
if(num && size) {
ret = calloc(num, size);
if(!ret) {
TSK_DEBUG_ERROR("Memory allocation failed. num=%u and size=%u", num, size);
}
}
return ret;
}
void* tsk_realloc (void* ptr, tsk_size_t size)
{
void *ret = tsk_null;
if(size) {
if(ptr) {
if(!(ret = realloc(ptr, size))) {
TSK_DEBUG_ERROR("Memory reallocation failed");
}
}
else {
if(!(ret = calloc(size, 1))) {
TSK_DEBUG_ERROR("Memory allocation (%u) failed", size);
}
}
}
return ret;
}
void tsk_free(void** ptr)
{
if(ptr && *ptr) {
free(*ptr);
*ptr = tsk_null;
}
}
static void _mix16(const int16_t* pInBufferPtr, float dInBufferVolume, int16_t* pOutBufferPtr, size_t nSizeToMixInBytes) {
uint32_t i;
float mixedSample;
size_t nSizeToMixInSamples = (nSizeToMixInBytes >> 1);
assert(pInBufferPtr&&pOutBufferPtr);
for(i = 0; i < nSizeToMixInSamples; ++i) {
mixedSample = ((float) pOutBufferPtr[i] / 32768.0f) + (((float) pInBufferPtr[i] / 32768.0f) * dInBufferVolume);
if(mixedSample < -1.0f) { mixedSample = -1.0f; }
if(mixedSample > +1.0f) { mixedSample = +1.0f; }
pOutBufferPtr[i] = (int16_t)(mixedSample * 32768.0f);
}
}
static audio_buffer_t* mix(audio_buffer_t* in_audios , float dInBufferVolume) {
int i;
audio_buffer_t* in=in_audios;
audio_buffer_t* out=tsk_null;
if(!in_audios) { goto FAIL; }
out=tsk_calloc(sizeof(audio_buffer_t),1);
if(!out) { goto FAIL; }
while(in) {
if(!out->audio) { out->audio=tsk_calloc(1,in->size*2); }
else if(out->size<in->size) {out->audio=tsk_realloc(out->audio,in->size*2); out->size=in->size;}
if(!out->audio) { goto FAIL; }
_mix16(in->audio,dInBufferVolume,out->audio,in->size);
in=in->next;
}
return out;
FAIL:
if(out&&out->audio) {
TSK_SAFE_FREE(out->audio);
}
TSK_SAFE_FREE(out);
return out;
}
int main()
{
int i;
audio_buffer_t* in=tsk_calloc(sizeof(audio_buffer_t),8);
audio_buffer_t* audio=in;
audio_buffer_t* out=NULL;
for( i=0; i<8; i++) {
audio->size=160;
audio->audio=tsk_calloc(1,audio->size*2);
if(i<7) {
audio->next=tsk_calloc(sizeof(audio_buffer_t),8);
audio=audio->next;
}
}
out=mix(in,0.8f);
return 0;
}