StreamingKit icon indicating copy to clipboard operation
StreamingKit copied to clipboard

Removing Silence

Open cerupcat opened this issue 8 years ago • 14 comments

Would it be possible to remove (or shorten) silence as audio plays? I don't think adding a filter will work since shortening silence will probably shorten the buffer, correct? Any recommendations for ways this could be achieved and what part of the code this may live?

cerupcat avatar Dec 30 '16 03:12 cerupcat

I'm researching it now. any news?

newbdez33 avatar Jun 09 '17 06:06 newbdez33

What silence? Silence between two songs?

iDevelopper avatar Jun 09 '17 06:06 iDevelopper

2012-02-29-15_53_12-1

newbdez33 avatar Jun 09 '17 06:06 newbdez33

I was able to do it, but not using any frameworks. It's been a while since I've looked at the code though (I'm not longer actively working on it right now). The idea is to remove any silence (or things under X db) from audio. For example, in a Podcast, when people talk, sometimes there's silent moments. Apps like PcketCasts and Overcast have the ability to remove silence in order to speed up listening. In your example above, yes removing that silent part and skipping to the next audio section.

cerupcat avatar Jun 09 '17 17:06 cerupcat

Hi @cerupcat I got the idea but I'm still not sure how to do it?

I tried "MTAudioProcessingTap", it looks like only allow me to get frames but I cannot remove frames. Any suggestion?

Thanks!

newbdez33 avatar Jun 10 '17 00:06 newbdez33

I'll have to look at my code later to fully remember, but the idea is you need an extra buffer. You need to look at the current frames and add frames that have volume (not silence) to a new buffer. Once that new (non-silence) buffer is full, you can play it.

cerupcat avatar Jun 11 '17 20:06 cerupcat

Is there way that we can use extra buffer for AVPlayer? I used to use this way to remove silence from recording.. but playing audio and replace buffer, I have no idea.. :(

newbdez33 avatar Jun 12 '17 05:06 newbdez33

@cerupcat please share code if you can :)

sameerkanda avatar Sep 18 '17 05:09 sameerkanda

@sameerkanda Here's a different solution than mine that might work. It's much simpler and potentially better (I haven't fully tried it yet). https://gist.github.com/dennisfedorko/143b2a42f7a139b47a44d23a728b0bc0

cerupcat avatar Sep 18 '17 06:09 cerupcat

@cerupcat Not exactly a perfect solution, but yea something along those lines would work (and that's what I was thinking of doing). Thanks!

sameerkanda avatar Sep 18 '17 06:09 sameerkanda

@sameerkanda I'll see if I can post mine later. It's very tied to my app so not easily abstracted away. It also probably needs some work since it's not adjustable like this example is and this one might actually work better with less battery usage (I'm not sure).

cerupcat avatar Sep 18 '17 17:09 cerupcat

Really appreciate it @cerupcat. I'm current working on a project and am stuck with this one thing. I'm not an iOS developer (I just know enough to mess around with it), so just having a hard time figuring this out. I think if I'm pointed in the right direction, I can probably figure the rest out. Thanks again!

sameerkanda avatar Sep 18 '17 17:09 sameerkanda

Did anyone get this to work in the end? Possibly have some code to share that might handle trimming silence?

patrickjquinn avatar Feb 06 '18 22:02 patrickjquinn

Hello,

I realise this thread is a little old, but I have a crude implementation that works. It's not great and you could certainly do this in a much better way by performing FFT or VAD analysis, looking ahead to where the sound envelope ends and skipping to that point. It's fairly intense though and requires a lot of thought..

Nonetheless, add the following to your AudioEngine class:

func scaledPower(power: Float) -> Float {
        guard power.isFinite else { return 0.0 }
        let minDb: Float = -80.0
        if power < minDb {
            return 0.0
        } else if power >= 1.0 {
            return 1.0
        } else {
            return (abs(minDb) - abs(power)) / abs(minDb)
        }
    }

    func connectVolumeTap() {
        let format = engine.mainMixerNode.outputFormat(forBus: 0)
        engine.mainMixerNode.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, when in
            guard let channelData = buffer.floatChannelData else {
                return
            }

            let channelDataValue = channelData.pointee
            let channelDataValueArray = stride(from: 0,
                                               to: Int(buffer.frameLength),
                                               by: buffer.stride).map { channelDataValue[$0] }

            let rms = sqrt(channelDataValueArray.map { $0 * $0 }.reduce(0, +) / Float(buffer.frameLength))

            let avgPower = 20 * log10(rms)

            let meterLevel = self.scaledPower(power: avgPower)
            if meterLevel < 0.6 {
                self.changeRate(to: 2)
            } else {
                self.changeRate(to: 1)
            }

        }
    }

jw1540 avatar Feb 19 '21 22:02 jw1540