sherpa-onnx icon indicating copy to clipboard operation
sherpa-onnx copied to clipboard

Apply Voice Effects Without Changing Sample Rates.

Open studionexus-lk opened this issue 1 year ago • 0 comments

I Added Voice Effects Like Baby,Chipmunk,Robot,Reverse Etc. This Works Fine , But Will This Drop The Quality Of The Audio?

 fun generateWithCallback(
        text: String,
        sid: Int = 0,
        speed: Float = 1.0f,
        effect: String? = null,
        callback: (samples: FloatArray) -> Unit
    ): GeneratedAudio {
        val objArray = generateWithCallbackImpl(ptr, text = text, sid = sid, speed = speed) { samples ->
            callback(samples)
            highlightCallback?.invoke(text)
        }

        val originalSamples = objArray[0] as FloatArray
        val originalSampleRate = objArray[1] as Int

        val processedSamples: FloatArray = when (effect) {
            "Chipmunk" -> applyChipmunkEffect(originalSamples, originalSampleRate)
            "Deep Voice" -> applyDeepVoiceEffect(originalSamples, originalSampleRate)
            "Echo" -> applyEchoEffect(originalSamples)
            "Reverse" -> applyReverseEffect(originalSamples)
            "Robot" -> applyRobotEffect(originalSamples)
            "Baby" -> applyBabyEffect(originalSamples, originalSampleRate)
            "Magic-Chords" -> applyMagicChordsEffect(originalSamples, originalSampleRate)
            else -> originalSamples
        }

        return GeneratedAudio(
            samples = processedSamples,
            sampleRate = originalSampleRate
        )
    }

    private fun applyBabyEffect(samples: FloatArray, originalSampleRate: Int): FloatArray {
        val newSampleRate = (originalSampleRate * 2.0).toInt()
        return changeSampleRate(samples, originalSampleRate, newSampleRate)
    }

    private fun applyMagicChordsEffect(samples: FloatArray, originalSampleRate: Int): FloatArray {
        val newSampleRate = (originalSampleRate * 1.25).toInt()
        return changeSampleRate(samples, originalSampleRate, newSampleRate)
    }

    private fun applyReverseEffect(samples: FloatArray): FloatArray {
        return samples.reversedArray()
    }

    private fun applyRobotEffect(samples: FloatArray, frequency: Int = 44100 / 40): FloatArray {
        val output = samples.copyOf()
        for (i in samples.indices) {
            if (i % frequency < frequency / 2) {
                output[i] = 0.0f
            }
        }
        return output
    }

    private fun applyEchoEffect(samples: FloatArray, delay: Int = 44100 / 4, decay: Float = 0.5f): FloatArray {
        val output = samples.copyOf()
        for (i in samples.indices) {
            if (i >= delay) {
                output[i] += decay * samples[i - delay]
            }
        }
        return output
    }

    private fun applyDeepVoiceEffect(samples: FloatArray, originalSampleRate: Int): FloatArray {
        val newSampleRate = (originalSampleRate * 0.75).toInt()
        return changeSampleRate(samples, originalSampleRate, newSampleRate)
    }

    private fun applyChipmunkEffect(samples: FloatArray, originalSampleRate: Int): FloatArray {
        val newSampleRate = (originalSampleRate * 1.5).toInt()
        return changeSampleRate(samples, originalSampleRate, newSampleRate)
    }

    private fun changeSampleRate(audioData: FloatArray, originalSampleRate: Int, newSampleRate: Int): FloatArray {
        val ratio = newSampleRate.toFloat() / originalSampleRate
        val newLength = (audioData.size / ratio).toInt()
        val newAudioData = FloatArray(newLength)

        for (i in newAudioData.indices) {
            val oldIndex = (i * ratio).toInt()
            newAudioData[i] = audioData[oldIndex]
        }

        return newAudioData
    }

studionexus-lk avatar Jul 29 '24 05:07 studionexus-lk