Page MenuHomePhabricator

simple_mixer.cpp
No OneTemporary

simple_mixer.cpp

//
// Created by yangjianli on 2019-09-09.
//
/**
* 输入一个音频和伴奏自动进行混合
* gated_loudness 当前音量
* gain 预期增益
*/
#include "iostream"
#include "WaveFile.h"
#include "math.h"
#include "ebur128.h"
#include "AudioMixer.h"
#include "alimiter.h"
#include "waves/inc/WaveFile.h"
#include "CAudioEffectsChainApi.h"
#include "string"
#include "ae_server/CAeServer.h"
#include <cstdio>
#include <chrono>
#include <iostream>
#include <cstdlib>
#include <sys/time.h>
#include "denoise/webrtc/include/WebrtcDenoise.h"
#define PROC_LEN 1024
#define DEFAULT_BASELINE_DB (float)-14.57f
int short2float(short *pInBuf, int nLen, float *pOutBuf)
{
for (int i = 0; i < nLen; i++)
{
pOutBuf[i] = pInBuf[i] * 1.0 / 32768;
}
return 0;
}
int float2short(float *pInBuf, int nLen, short *pOutBuf)
{
for (int i = 0; i < nLen; i++)
{
pOutBuf[i] = int(pInBuf[i] * 32768);
}
return 0;
}
/**
* 获取增益
* @param nChannel
* @param nSampleRate
* @param pData
* @param nLength
* @param gain
* @return
*/
int ebur128_whole(int nChannel, int nSampleRate, short *pData, const int nLength, double &gated_loudness, double &gain)
{
printf("ebur128_init start .. %d\n", nLength);
ebur128_state *st = NULL;
st = ebur128_init(nChannel, nSampleRate, EBUR128_MODE_I);
if (NULL == st)
{
return -1;
}
int nPos = 0;
int nTmpLength = 0;
int nRet;
printf("process start ..\n");
while (nPos < nLength)
{
nTmpLength = PROC_LEN;
if (nLength - nPos < PROC_LEN)
{
nTmpLength = nLength - nPos;
}
nRet = ebur128_add_frames_short(st, pData + nPos, nTmpLength / nChannel);
if (nRet != 0)
{
return -2;
}
nPos += nTmpLength;
}
printf("process ok..\n");
gated_loudness = -1;
ebur128_loudness_global(st, &gated_loudness);
float db = (DEFAULT_BASELINE_DB - gated_loudness) / 20.f;
gain = pow(10, db);
printf("gated_loudness = %f db = %f gain = %f\n", gated_loudness, db, gain);
ebur128_destroy(&st);
return 0;
}
/**
* 混合音频和伴奏
* @param pVocalIn
* @param pAccIn
* @param nLength
* @param gainVocal
* @param gainAcc
* @param pOutBuf
* @return
*/
int mix(float *pVocalIn, float *pAccIn, int nLength, double gainVocal, double gainAcc, float *pOutBuf,
int nSampleRate, int nChannel, int nDelay)
{
CAudioMixer *cAudioMixer = new CAudioMixer();
cAudioMixer->init(nSampleRate, nChannel);
cAudioMixer->set_acc_delay(nDelay);
cAudioMixer->set_vocal_volume(int(gainVocal * 50));
cAudioMixer->set_acc_volume(int(gainAcc * 50));
int nPos = 0;
int nStep = 1024;
float *fTmp = new float[nStep];
cAudioMixer->reset();
nPos = 0;
nStep = 1024;
int cnt = 0;
while (nPos < nLength)
{
if (nLength - nPos < nStep)
{
nStep = nLength - nPos;
}
cnt++;
cAudioMixer->process(pVocalIn + nPos, pAccIn + nPos, pOutBuf + nPos, nStep);
nPos += nStep;
}
delete cAudioMixer;
delete[] fTmp;
return 0;
}
int denoise_webrtc(short *pInBuf, int nLength, int nChannel, int nSampleRate)
{
CWebrtcDenoise cWebrtcDenoise;
cWebrtcDenoise.init(nSampleRate, nChannel);
float *pTmp = new float[nLength];
for (int i = 0; i < nLength; i++)
{
pTmp[i] = pInBuf[i] * 1.0 / 32768;
}
cWebrtcDenoise.set_level(kHigh);
int nStep = 512 * nChannel;
for (int i = 0; i < nStep; i++)
{
pTmp[i] = pTmp[i] * i * 1.0 / nStep;
}
for (int i = 0, cnt = 0; i < nLength; i += nStep, cnt++)
{
if (nLength - i < nStep) continue;
cWebrtcDenoise.process(pTmp + i, nStep);
}
for (int i = 0; i < nLength; i++)
{
pInBuf[i] = short(pTmp[i] * 32768);
}
delete[] pTmp;
return 0;
}
double calc_power_rate(float *in_data, int32_t in_len, float *ref_data, int32_t ref_len)
{
double in_power = 0;
double ref_power = 0;
int32_t min_len = in_len > ref_len ? ref_len : in_len;
for (int i = 0; i < min_len; i++)
{
in_power += (in_data[i]) * (in_data[i]);
ref_power += (ref_data[i]) * (ref_data[i]);
}
return ref_power / in_power;
}
int main(int argc, char *argv[])
{
if (argc != 4)
{
printf("input error! example: ./main vocal_path acc_path mix_path\n");
return -1;
}
std::string sVocal = argv[1];
std::string sAcc = argv[2];
std::string sMix = argv[3];
// 读取人声
CWaveFile *oWaveFile = new CWaveFile(sVocal.c_str(), false);
float *pfVocalBuf = new float[oWaveFile->GetTotalFrames() * oWaveFile->GetChannels()];
oWaveFile->ReadFrameAsfloat(pfVocalBuf, oWaveFile->GetTotalFrames());
//读取伴奏
CWaveFile *oWaveFile1 = new CWaveFile(sAcc.c_str(), false);
float *pfAccBuf = new float[oWaveFile1->GetTotalFrames() * oWaveFile1->GetChannels()];
oWaveFile1->ReadFrameAsfloat(pfAccBuf, oWaveFile1->GetTotalFrames());
if (oWaveFile->GetChannels() != oWaveFile1->GetChannels())
{
printf("channel not equal!\n");
return -1;
}
// 混合音频和伴奏
printf("mix wav:%s and acc:%s!\n", sVocal.c_str(), sAcc.c_str());
int nOutLen = oWaveFile->GetTotalFrames() < oWaveFile1->GetTotalFrames() ? oWaveFile->GetTotalFrames()
: oWaveFile1->GetTotalFrames();
nOutLen = nOutLen * oWaveFile->GetChannels();
float *pOutBuf = new float[nOutLen];
mix(pfVocalBuf, pfAccBuf, nOutLen, 1.0, 1.0, pOutBuf, oWaveFile->GetSampleRate(), oWaveFile->GetChannels(), 0);
//写入文件
printf("write2file nLength:%d path:%s!\n", nOutLen, sMix.c_str());
CWaveFile *oWaveFile2 = new CWaveFile(sMix.c_str(), true);
oWaveFile2->SetSampleFormat(SF_IEEE_FLOAT);
oWaveFile2->SetSampleRate(oWaveFile->GetSampleRate());
oWaveFile2->SetChannels(oWaveFile->GetChannels());
oWaveFile2->SetupDone();
oWaveFile2->WriteFrame(pOutBuf, nOutLen / oWaveFile->GetChannels());
delete oWaveFile;
delete oWaveFile1;
delete oWaveFile2;
delete[] pfVocalBuf;
delete[] pfAccBuf;
delete[] pOutBuf;
return 0;
}

File Metadata

Mime Type
text/x-c
Expires
Sun, Nov 24, 21:23 (23 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1326547
Default Alt Text
simple_mixer.cpp (6 KB)

Event Timeline