2017-02-21 3 views
0

J'essaie d'effectuer une mise à l'échelle linéaire d'une entrée audio, avec la même mise à l'échelle sur chaque canal.Mise à l'échelle du son Java

L'effet global est que le flux d'entrée diminue graduellement en amplitude jusqu'à ce qu'il soit silencieux. Donc, mon premier échantillon restera le même et mon dernier échantillon sera égal à 0 en termes d'amplitude. Je me demandais comment vous implémentez cela. Jusqu'ici, voici ce que j'ai du code de mise à l'échelle et je me demandais si vous deviez encore mettre à l'échelle l'échantillon de façon à ce qu'il se situe entre les 16 chiffres de la gamme de complément à deux chiffres.

for (int i=0; i<data.length; ++i){ // data[i] is sample in intger form 
     data[i] = (int) (data[i]*(something/something)); 
} 

Il serait utile si la mise à l'échelle d'un facteur spécifique pouvait être expliquée?

Merci!

+1

Quelle est votre véritable question? Si vous avez correctement fait la mise à l'échelle et que vous réduisez seulement l'amplitude, elle sera automatiquement dans une plage de 16 bits. Cependant, votre code est incorrect - pourquoi avez-vous besoin de multiplier l'échantillon par la valeur maximale - ce qui en fait une plage de 32 bits et beaucoup plus fort? Et que se passe-t-il si vous divisez par zéro dans la première itération de votre boucle? Avez-vous même exécuté le code? –

+0

@erwin bolwidt ma question est de savoir comment vous mettre à l'échelle linéairement à 0. Est-ce que je juste diviser chaque échantillon par 0? – Hawwa

Répondre

1

Je suppose que vous travaillez avec des valeurs courtes pour vos données audio (par exemple, [-32768..32767]) et que la conversion de et vers des octets est gérée ailleurs.

Dans votre fraction, "quelque chose/quelque chose", le numérateur irait d'une valeur égale au dénominateur jusqu'à zéro alors que le dénominateur reste une valeur fixe. Par exemple, si vous divisez la plage de volume en 128 étapes, le volume le plus fort serait de 128/128, le volume le plus faible serait de 0/128.

Pour éviter la division, vous pouvez précalculer le facteur égal à 1/128 et le multiplier par une valeur comprise dans l'intervalle [0..128] inclus.

Ensuite, vous auriez "quelque chose * precalculatedFactor" qui pourrait fonctionner un peu plus rapidement. Mais il existe des problèmes liés à la mise à l'échelle linéaire du volume. Le volume perçu réel ne suit pas linéairement. Ainsi, un intervalle de volume de X peut à peine créer une différence de volume à l'extrémité supérieure, mais sera si important qu'il entraînera une discontinuité et un clic à l'extrémité inférieure.

Je pense que les gens utilisent souvent une fonction exponentielle pour mieux faire correspondre le volume à une entrée linéaire. Il y a des désaccords quant à ce qui est le meilleur. Mais supposons que votre cadran de volume passe de [0..1]. Si vous divisez la valeur avant de l'appliquer, par exemple, une entrée de 0,5 dans une tentative de création de 1/2 du volume devient (0,5 * 0,5 * 0,5) => 0,125, ce qui sera plus proche de 1/2 volume que 0,5.

Ainsi, "quelque chose * quelque chose * quelque chose * precalculatedFactorCubed" pourrait fonctionner mieux.

+0

comment fonctionne l'utilisation de deux canaux avec la mise à l'échelle? – Hawwa

+0

Les canaux alternent à gauche et à droite. Vous devez appliquer les mêmes facteurs et le même calcul à chacune des deux valeurs. –