Search code examples
qtffmpeg

How to change volume of an audio AVPacket


I have a desktop Qt-based application that fetches a sound stream from the network and plays it using QAudioOutput. I want to provide a volume control to the user so that he can reduce the volume. My code looks like this:

float volume_control = get_user_pref(); // user provided volume level {0.0,1.0}

for (;;) {
    AVPacket *retrieved_pkt = get_decoded_packet_stream();  // from network stream

    AVPacket *work_pkt
       = change_volume(retrieved_pkt, volume_control); // this is what I need

    // remaining code to play the work_pkt ...
}

How do I implement change_volume() or is there any off the shelf function that I can use?

Edit: Adding codec-related info as requested in the comments

QAudioFormat format;
format.setFrequency(44100);
format.setChannels(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);

Solution

  • The following code works just fine.

    // audio_buffer is a byte array of size data_size 
    // volume_level is a float between 0 (silent) and 1 (original volume)
    
    int16_t * pcm_data  = (int16_t*)(audio_buffer);
    int32_t pcmval;
    for (int ii = 0; ii < (data_size / 2); ii++) {   // 16 bit, hence divided by 2
        pcmval = pcm_data[ii] * volume_level ;
        pcm_data[ii] = pcmval;
    }
    

    Edit: I think there is a significant scope of optimization here, since my solution is compute-intensive. I guess avcodec_decode_audio() can be used to speed it up.