1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > ffmpeg+soundtouch实现音频变速变调

ffmpeg+soundtouch实现音频变速变调

时间:2021-06-10 02:26:06

相关推荐

ffmpeg+soundtouch实现音频变速变调

实现并不难,本人只贴出相关代码,想要详细了解的朋友可以另行百度一下

相关参数设置和部分用到的函数定义

typedef float SAMPLETYPE;#define BUFF_SIZE 6720static char *convBuff = NULL;int convBuffSize = 0;void * getConvBuffer(int sizeBytes){if (convBuffSize < sizeBytes){delete[] convBuff;convBuffSize = (sizeBytes + 15) & -8; // round up to following 8-byte boundayconvBuff = new char[convBuffSize];}return convBuff;}static inline short _swap16(short &wData){return wData;}int readHandle(float *buffer, int maxElems, FILE *fptr){int bytesPerSample = 2;int numBytes = maxElems * 2;char *temp = (char*)getConvBuffer(numBytes);numBytes = (int)fread(temp, 1, numBytes, fptr);int numElems = numBytes / bytesPerSample;short *temp2 = (short*)temp;double conv = 1.0 / 32768.0;for (int i = 0; i < numElems; i++){short value = temp2[i];buffer[i] = (float)(_swap16(value) * conv);}return numElems;}inline int saturate(float fvalue, float minval, float maxval){if (fvalue > maxval){fvalue = maxval;}else if (fvalue < minval){fvalue = minval;}return (int)fvalue;}void writeHandle(const float *buffer, int numElems, FILE *fptr){int numBytes;int bytesPerSample;if (numElems == 0) return;bytesPerSample = 2;numBytes = numElems * bytesPerSample;void *temp = getConvBuffer(numBytes + 7); // round bit up to avoid buffer overrun with 24bit-value assignmentshort *temp2 = (short *)temp;for (int i = 0; i < numElems; i++){short value = (short)saturate(buffer[i] * 32768.0f, -32768.0f, 32767.0f);temp2[i] = _swap16(value);}int res = (int)fwrite(temp, 1, numBytes, fptr);if (res != numBytes){//ST_THROW_RT_ERROR("Error while writing to a wav file.");}}void writeWavHeader(AVCodecContext *pCodecCtx, AVFormatContext *pFormatCtx, FILE *audioFile){//wav文件有44字节的wav头,所以要写44字节的wav头int8_t *data;UINT32 long_temp;UINT16 short_temp;UINT16 BlockAlign;int bits = 8;UINT64 fileSize;UINT64 audioDataSize;switch (pCodecCtx->sample_fmt){case AV_SAMPLE_FMT_S16:bits = 16;break;case AV_SAMPLE_FMT_S32:bits = 32;break;case AV_SAMPLE_FMT_U8:bits = 8;break;default:bits = 16;break;}audioDataSize = (pFormatCtx->duration)*(bits / 8)*(pCodecCtx->sample_rate)*(pCodecCtx->channels);fileSize = audioDataSize + 36;data = (int8_t *)"RIFF";fwrite(data, sizeof(char), 4, audioFile);fwrite(&fileSize, sizeof(int32_t), 1, audioFile);data = (int8_t *)"WAVE";fwrite(data, sizeof(char), 4, audioFile);data = (int8_t *)"fmt ";fwrite(data, sizeof(char), 4, audioFile);long_temp = 16;fwrite(&long_temp, sizeof(int32_t), 1, audioFile);short_temp = 0x01;fwrite(&short_temp, sizeof(int16_t), 1, audioFile);short_temp = (pCodecCtx->channels);fwrite(&short_temp, sizeof(int16_t), 1, audioFile);long_temp = (pCodecCtx->sample_rate);fwrite(&long_temp, sizeof(int32_t), 1, audioFile);long_temp = (bits / 8)*(pCodecCtx->channels)*(pCodecCtx->sample_rate);fwrite(&long_temp, sizeof(int32_t), 1, audioFile);BlockAlign = (bits / 8)*(pCodecCtx->channels);fwrite(&BlockAlign, sizeof(int16_t), 1, audioFile);short_temp = (bits);fwrite(&short_temp, sizeof(int16_t), 1, audioFile);data = (int8_t *) "data";fwrite(data, sizeof(char), 4, audioFile);fwrite(&audioDataSize, sizeof(int32_t), 1, audioFile);}

实现变速变调的重要相关代码

string filename = "c:\\test.wav";AVCodecContext *pCodecCtx;av_register_all();AVFormatContext *ifmt_ctx = NULL;int AudioStreamIndex = -1;int ret = -1;if ((ret = avformat_open_input(&ifmt_ctx, filename.c_str(), NULL, NULL)) < 0){printf("can not open input");return;}if ((ret = avformat_find_stream_info(ifmt_ctx, NULL))){printf("can not find input stream info");return;}//open the decoder for (int i = 0; i <(int)ifmt_ctx->nb_streams; i++){if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){AudioStreamIndex = i;pCodecCtx = ifmt_ctx->streams[AudioStreamIndex]->codec;}}float rateDelta = 0.0; //变速变调float pitchDelta = 5.0; //变调不变速float tempoDelta = 0.0; //变速不变调 +(加速 时长变短) -(减速 时长变长)HANDLE handle = soundtouch_createInstance();soundtouch_setSampleRate(handle, pCodecCtx->sample_rate); // 设置采样率soundtouch_setChannels(handle, pCodecCtx->channels); // 设置通道数soundtouch_setRateChange(handle, rateDelta); soundtouch_setPitchSemiTones(handle, pitchDelta); //变速变调soundtouch_setTempoChange(handle, tempoDelta);string strOutFileNameAdd;if (rateDelta != 0.0){if (rateDelta > 0.0)strOutFileNameAdd += "_rate+" + to_string(abs((int)rateDelta));elsestrOutFileNameAdd += "_rate-" + to_string(abs((int)rateDelta));}if (pitchDelta != 0){if (pitchDelta > 0)strOutFileNameAdd += "_pitch+" + to_string(abs((int)pitchDelta));elsestrOutFileNameAdd += "_pitch-" + to_string((int)pitchDelta);}if (tempoDelta != 0){if (tempoDelta > 0)strOutFileNameAdd += "_tempo+" + to_string(abs((int)tempoDelta));elsestrOutFileNameAdd += "_tempo-" + to_string(abs((int)tempoDelta));}FILE *pOut = NULL;char tmpName[100];sprintf_s(tmpName, "%s_%d_%dchannel_%s.wav", filename.c_str(), ifmt_ctx->streams[AudioStreamIndex]->codec->sample_rate, ifmt_ctx->streams[AudioStreamIndex]->codec->channels, strOutFileNameAdd.c_str());pOut = fopen(tmpName, "wb");if (AudioStreamIndex >= 0)pCodecCtx = ifmt_ctx->streams[AudioStreamIndex]->codec;writeWavHeader(pCodecCtx, ifmt_ctx, pOut);int nSamples = 0;int nChannels = pCodecCtx->channels;;int buffSizeSamples = BUFF_SIZE / nChannels;;SAMPLETYPE sampleBuffer[BUFF_SIZE];FILE *fptr = fopen(filename.c_str(), "rb");fseek(fptr, 44, SEEK_SET);//这里偏移44个字节,是因为wav的头部信息为44位while (feof(fptr) == 0){int num = readHandle(sampleBuffer, BUFF_SIZE, fptr);// Read a chunk of samples from the input filenSamples = num / nChannels;// Feed the samples into SoundTouch processorsoundtouch_putSamples(handle, sampleBuffer, nSamples);do{nSamples = soundtouch_receiveSamples(handle, sampleBuffer, buffSizeSamples);writeHandle(sampleBuffer, nSamples * nChannels, pOut);} while (nSamples != 0);}soundtouch_flush(handle);do{nSamples = soundtouch_receiveSamples(handle, sampleBuffer, buffSizeSamples);writeHandle(sampleBuffer, nSamples * nChannels, pOut);} while (nSamples != 0);fclose(fptr);fclose(pOut);avcodec_close(pCodecCtx);avformat_close_input(&ifmt_ctx);

SoundTouch通过动态引用,具体文件有SoundTouchDLL.h,SoundTouchDLL.lib和SoundTouchDLL.dll,实现时用的版本是soundtouch_dll-2.1.0.zip,SoundTouch官网上可以下载

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。