You need to enable JavaScript to run this app.
导航

【C】响度检测

最近更新时间2023.03.16 11:40:13

首次发布时间2023.03.16 11:40:13

完整例子
SAMICoreFeatureArray* findWantedFeature(SAMICoreFeatureSet* f_set, SAMICorePropertyId feature_id) {
    for(int i = 0; i < f_set->numFeatureTypes; ++i) {
        if(f_set->set[i].featureID == feature_id) { return &(f_set->set[i]); }
    }
    return nullptr;
}


// step 1, create handle
const int sample_rate = 48000 ; 
const int num_channels = 2;

SAMICoreHandle handle;
SAMICoreExtractorCreateParam param;
param.sampleRate = sample_rate;
param.numChannel = num_channels;
int ret = SAMICoreCreateHandleByIdentify(&handle, SAMICoreIdentify::SAMICoreIdentify_Extractor_Loudness, &createParameter);


// step 2, create input audio block
SAMICoreAudioBuffer in_audio_buffer;
in_audio_buffer.numberChannels = num_channels;
in_audio_buffer.numberSamples = block_size;
in_audio_buffer.data = new float *[num_channels];
in_audio_buffer. isInterleave = 0;

for(int c = 0; c < int(num_channels); ++c){
    in_audio_buffer.data[c] = new float[block_size];
}

SAMICoreBlock in_block;
in_block.dataType = SAMICoreDataType::SAMICoreDataType_AudioBuffer;
in_block.numberAudioData = 1;
in_block.audioData = &in_audio_buffer;

// step 3, process block by block
for(;hasAudioSamples();)
{
    copySamplesToInputBuffer(in_audio_buffer);
    int ret = SAMICoreProcess(handle, &in_block, NULL);
    assert(ret == SAMI_OK);
    
    //step 4,get SHORTTERM_LOUDNESS
    SAMICoreProperty frame_features;
    SAMICoreGetPropertyById(handle, SAMICorePropertyID_FrameFeatures, &frame_features);
    
    auto frame_feature_set = (SAMICoreFeatureSet*)(frame_features.data);
    
    {
        SAMICoreFeatureArray* feature = findWantedFeature(frame_feature_set, SAMICorePropertyID_FrameFeature_SHORTTERM_LOUDNESS);
        if(feature != nullptr) {    
            auto time = feature->array[0].time;
            for(auto i = 0u; i < feature->array[0].numValues; ++i) {
                cout << "SHORTTERM_LOUDNESS:"  << "  time:" << time << "   values:" << feature->array[0].values[i] << endl;
            }
        }
    }

    {
        SAMICoreFeatureArray* feature = findWantedFeature(frame_feature_set, SAMICorePropertyID_FrameFeature_MOMENTARY_LOUDNESS);
        if(feature != nullptr) {
            auto time = feature->array[0].time;
            for(auto i = 0u; i < feature->array[0].numValues; ++i) {
                cout << "MOMENTARY_LOUDNESS:" << "  time:" << time << "   values:" << feature->array[0].values[i] << endl;
            }
        }
    }
    

    SAMICoreDestroyProperty(&frame_features);
}

// step 5, get source global loudness and peak
SAMICoreProperty overall_features;
SAMICoreGetPropertyById(handle, 
                        SAMICorePropertyID_OverallFeatures, 
                        &overall_features);
SAMICoreFeatureSet* feature_set = (SAMICoreFeatureSet*)(overall_features.data);
if(feature_set != NULL) {
    SAMICoreFeatureArray* loudness_results =findWantedFeature(feature_set, 
                SAMICorePropertyID_OverallFeature_GLOBAL_LOUDNESS);
    if(loudness_results != NULL){
        for(size_t i = 0; i < loudness_results->numFeatures; ++i) 
        {
            float source_lufs = loudness_results->array[i].values[0];
            cout << "source_lufs:" << source_lufs << endl;
        }
    }
    
    SAMICoreFeatureArray* peak_results =findWantedFeature(feature_set, 
                SAMICorePropertyID_OverallFeature_GLOBAL_PEAK);
    if(peak_results != NULL){
        for(size_t i = 0; i < peak_results->numFeatures; ++i) 
        {
            float peak = peak_results->array[i].values[0];
            cout << "peak:" << peak << endl;
        }
    }
}
SAMICoreDestroyProperty(&overall_features);

// step 5, release resource
ret = SAMICoreDestroyHandle(handle);
assert(ret == SAMI_OK);

for(int c = 0; c < int(num_channels); ++c){
    delete [] in_audio_buffer.data[c];
}

delete [] in_audio_buffer.data;
使用步骤

一、创建算法句柄

传入采样率、声道数和 maxBlockSize(每次处理的最大采样点),通过 创建 handle。

const int sample_rate = 48000 ; 
const int num_channels = 2;

SAMICoreHandle handle;
SAMICoreExtractorCreateParam param;
param.sampleRate = sample_rate;
param.numChannel = num_channels;
int ret = SAMICoreCreateHandleByIdentify(&handle, SAMICoreIdentify::SAMICoreIdentify_Extractor_Loudness, &createParameter);

二、创建 SAMICoreBlock 用于存放输入和输出

SAMICoreAudioBuffer,用于存放音频数据。
SAMICoreBlock,用于存放需要处理的数据。

SAMICoreAudioBuffer in_audio_buffer;
in_audio_buffer.numberChannels = num_channels;
in_audio_buffer.numberSamples = block_size;
in_audio_buffer.data = new float *[num_channels];
in_audio_buffer. isInterleave = 0;

for(int c = 0; c < int(num_channels); ++c){
    in_audio_buffer.data[c] = new float[block_size];
}

SAMICoreBlock in_block;
in_block.dataType = SAMICoreDataType::SAMICoreDataType_AudioBuffer;
in_block.numberAudioData = 1;
in_block.audioData = &in_audio_buffer;

三、处理音频,并获取检测结果

拷贝数据进行处理

将待处理的音频数据拷贝到 in_audio_buffer 中,再经 SAMICoreProcess 处理

for(;hasAudioSamples();)
{
    copySamplesToInputBuffer(in_audio_buffer);
    int ret = SAMICoreProcess(handle, &in_block, NULL);
    assert(ret == SAMI_OK);
}

In-Place 进行处理

更新音频数据的指针,指向正确的内存即可,这样可以避免内存数据的拷贝。

for(;hasAudioSamples();)
{
    updateInpuBuffer(in_audio_buffer);
    int ret = SAMICoreProcess(handle, &in_block, NULL);
    assert(ret == SAMI_OK);
}

四、获取短时响度和瞬时响度

SHORTTERM_LOUDNESS 是获取最近3s的响度
MOMENTARY_LOUDNESS 是获取最近400ms的响度

SAMICoreProperty frame_features;
SAMICoreGetPropertyById(handle, SAMICorePropertyID_FrameFeatures, &frame_features);

auto frame_feature_set = (SAMICoreFeatureSet*)(frame_features.data);

{
    SAMICoreFeatureArray* feature = findWantedFeature(frame_feature_set, SAMICorePropertyID_FrameFeature_SHORTTERM_LOUDNESS);
    if(feature != nullptr) {
        auto time = feature->array[0].time;
        for(auto i = 0u; i < feature->array[0].numValues; ++i) {
            cout << "SHORTTERM_LOUDNESS:" << "  time:" << time << "   values:" << feature->array[0].values[i] << endl;
        }
    }
}

{
    SAMICoreFeatureArray* feature = findWantedFeature(frame_feature_set, SAMICorePropertyID_FrameFeature_MOMENTARY_LOUDNESS);
    if(feature != nullptr) {
        auto time = feature->array[0].time;
        for(auto i = 0u; i < feature->array[0].numValues; ++i) {
            cout << "MOMENTARY_LOUDNESS:" << "  time:" << time << "   values:" << feature->array[0].values[i] << endl;
        }
    }
}

SAMICoreDestroyProperty(&frame_features);

五、获取整体响度、峰值

待处理完整个音频,通过 SAMICoreGetPropertyById 获取整体响度和峰值

SAMICoreProperty overall_features;
SAMICoreGetPropertyById(handle, 
                        SAMICorePropertyID_OverallFeatures, 
                        &overall_features);
SAMICoreFeatureSet* feature_set = (SAMICoreFeatureSet*)(overall_features.data);
if(feature_set != NULL) {
    SAMICoreFeatureArray* loudness_results =findWantedFeature(feature_set, 
                SAMICorePropertyID_OverallFeature_GLOBAL_LOUDNESS);

    if(loudness_results != NULL){
        for(size_t i = 0; i < loudness_results->numFeatures; ++i) 
        {
            float source_lufs = loudness_results->array[i].values[0];
            cout << "source_lufs:" << source_lufs << endl;
        }
    }
    
    SAMICoreFeatureArray* peak_results =findWantedFeature(feature_set, 
                SAMICorePropertyID_OverallFeature_GLOBAL_PEAK);
                
     if(peak_results != NULL){
        for(size_t i = 0; i < peak_results->numFeatures; ++i) 
        {
            float source_peak = peak_results->array[i].values[0];
            cout << "source_peak:" << source_peak << endl;
        }
    }
}
SAMICoreDestroyProperty(&overall_features);

六、释放资源

ret = SAMICoreDestroyHandle(handle);

此外,还要注意音频数据数据的内存释放(如果有)。例如:

for(int c = 0; c < int(num_channels); ++c){
    delete [] in_audio_buffer.data[c];
}

delete [] in_audio_buffer.data;