Hallo,
ich möchte in meinem aktuellen Programm die Funktionalität, Sounds mit veränderter Tonhöhe und Geschwindigkeit* abzuspielen anhand von Faktoren wie 0.4 oder 1.7 . Die Sounds habe ich im .wav-Format (16bit) vorliegen. Da ich nun aber seit 2 Tagen rumprobiere, teste und versuche und die Ergebnisse recht kläglich bleiben, möchte ich hier Hilfe/Unterstützung erbitten (und würde mich natürlich sehr freuen wenn ich sie auch bekomme )
Hier nun also meine bisherigen Versuche:
Zunächst die Konvertierung: Da ich ja 2 byte pro Frame "geliefert" bekam, hab ich diese mit folgendem in ein Int-Array (das dann bearbeitet wurde) gepackt und später wieder zurückkonvertiert:
Hier mein 1. Algorithmus (als erster Anlauf ein meinem Empfinden nach eher grobes Gehacke, das aber interessanterweise noch eher in manchen Fällen nach dem Original klingt als mein zweiter Versuch):
Hier mein zweiter Versuch, diesmal unter dem Leitmotiv, den "Streckfaktor" zu verzehnfachen, die Lücken mit "linearen Übergängen" zu füllen ({60, 0, 0, 30} -> {60, 50, 40, 30}) und dann aus diesem Array jeden zehnten Wert in das "finale" Array einzulesen.
Wie gesagt, für Ratschläge/Hinweise/Tipps/Hilfe wäre ich sehr dankbar
*sowohl aus Gründen der "Einfachheit" als auch aus Designgründen
ich möchte in meinem aktuellen Programm die Funktionalität, Sounds mit veränderter Tonhöhe und Geschwindigkeit* abzuspielen anhand von Faktoren wie 0.4 oder 1.7 . Die Sounds habe ich im .wav-Format (16bit) vorliegen. Da ich nun aber seit 2 Tagen rumprobiere, teste und versuche und die Ergebnisse recht kläglich bleiben, möchte ich hier Hilfe/Unterstützung erbitten (und würde mich natürlich sehr freuen wenn ich sie auch bekomme )
Hier nun also meine bisherigen Versuche:
Zunächst die Konvertierung: Da ich ja 2 byte pro Frame "geliefert" bekam, hab ich diese mit folgendem in ein Int-Array (das dann bearbeitet wurde) gepackt und später wieder zurückkonvertiert:
Java:
static int[] toUnsignedByte(byte[] b)
{
int[] ret = new int[b.length/2];
for(int i=0; i<ret.length; i++)
{
ret[i] = (int)(( ((int)b[i*2]) << 8) | ((int)b[i*2+1]));
}
return ret;
}
static byte[] toByte(int[] i)
{
byte[] ret = new byte[i.length*2];
for(int j=0; j<i.length; j++)
{
ret[j*2] = (byte) (i[j] >> 8);
ret[j*2+1] = (byte) (i[j] & 255);
}
return ret;
}
Java:
static byte[] pitch(int[] toPlay/*das "Originalarray" wurde bereits in konvertierter Form geliefert*/, float var)
{
float stretchFact = (1/var);
int[] neu = new int[Math.round(toPlay.length*(1/var))];
for(int i=0; i<neu.length; i++)
{
neu[i] = toPlay[(int)(i/stretchFact)];
}
int[] geglättet = new int[neu.length];
geglättet[0] = neu[0];
for( int i=1; i<neu.length-1; i++)
{
if(i % stretchFact == 0)
{
geglättet[i] = neu[i];
continue;
}
geglättet[i] = (int)((neu[i-1]*2+neu[i]+neu[i+1]*2) / 5.0 + 0.5);
}
geglättet[neu.length-1] = neu[neu.length-1];
for(int i = 0; i < geglättet.length; i++)
if(Math.round(stretchFact*i) < geglättet.length)
geglättet[Math.round(stretchFact*i)] = toPlay[i];
return toByte(geglättet);
}
Hier mein zweiter Versuch, diesmal unter dem Leitmotiv, den "Streckfaktor" zu verzehnfachen, die Lücken mit "linearen Übergängen" zu füllen ({60, 0, 0, 30} -> {60, 50, 40, 30}) und dann aus diesem Array jeden zehnten Wert in das "finale" Array einzulesen.
Java:
static byte[] pitch(int[] toPlay/*das "Originalarray" wurde bereits in konvertierter Form geliefert*/, float var)
{
int stretchFact = (int)((1/var)*10 + 0.5F);
int[] temp = new int[toPlay.length*stretchFact];
for(int i=0; i<toPlay.length; i++)
{
temp[i*stretchFact] = toPlay[i];
}
int step;
for(int i=0; i<temp.length; i++)
{
step = i % stretchFact;
if(step == 0)
continue;
try { temp[i] = ( toPlay[i/stretchFact] + toPlay[(i+stretchFact)/stretchFact] )*step/stretchFact; } catch(ArrayIndexOutOfBoundsException e) {}
}
int[] ret = new int[(int) (toPlay.length*(1/var)+0.5)];
for(int i=0; i<ret.length; i++)
try { ret[i] = temp[i*10]; } catch(ArrayIndexOutOfBoundsException e) {}
return toByte(ret);
Wie gesagt, für Ratschläge/Hinweise/Tipps/Hilfe wäre ich sehr dankbar
*sowohl aus Gründen der "Einfachheit" als auch aus Designgründen