Aus PCM16BitStereo mach PCM8BitMono?

Eroli

Erfahrenes Mitglied
Hallo zusammen,

für ein Microcontrollerprojekt muss ich eine MP3-Datei stark abspecken, damit der kleine Controller nicht überfordert ist.
Mittels MP3Sharp dekodiere ich die MP3-Datei in ihre PCM-Rohdaten.
Dann durchlaufe ich diese Daten und versuche sie entsprechend zu filtern.

Der Schritt Stereo --> Mono hat nach einigen Testen auch gut geklappt, allerdings kriege ich das 16Bit --> 8 Bit nicht hin.

Wenn ich die Datei mit CoolEditPro öffne, wird sie im Intel 16bit-PCM Format (LSB, MSB) korrekt abgespielt, also dachte ich mir, dass mir im zweiten Schritt einfach nur jedes zweites Byte (immer das MSB) nehmen kann um damit eine 8Bit-Version zu erschaffen.

Hier mein Code:
C#:
byte[] audioLinkBuffer = new byte[1000];

                    while (m_MP3Stream.Read(audioLinkBuffer, 0, audioLinkBuffer.Length) != 0)
                    {
                        byte[] b = new byte[audioLinkBuffer.Length / 2];
                        int k = 0;
                        for (int i = 1; i < audioLinkBuffer.Length; i += 4)
                        {
                            for (int j = 0; j <= 1; j++)
                            {
                                b[k] = audioLinkBuffer[i + j - 1];              // Aus Stereo mach Mono
                                k++;
                            }
                        }
                        k = 0;
                        byte[] c = new byte[b.Length / 2];
                        for (int i = 0; i + 1 < c.Length; i += 2)
                        {
                            c[k] = b[i + 1];                      // Nur High-Byte filtern (funktioniert nicht)
                            k++;
                        }
                        outputStream.Write(c, 0, c.Length);
                    }
                    outputStream.Flush();
                    outputStream.Close();

Habt ihr da vielleicht irgendwelche Ideen oder Vorschläge?
 

Eroli

Erfahrenes Mitglied
Habe herausgefunden, dass 16Bit-PCM im 2er-Komplement gespeichert wird.

Nun sieht mein Code so aus (ich weiß der ist nicht optimiert):
C#:
while (m_MP3Stream.Read(audioLinkBuffer, 0, audioLinkBuffer.Length) != 0)
                    {
                        byte[] b = new byte[audioLinkBuffer.Length / 2];
                        int k = 0;
                        for (int i = 1; i < audioLinkBuffer.Length; i += 4)
                        {
                            for (int j = 0; j <= 1; j++)
                            {
                                b[k] = audioLinkBuffer[i + j - 1];              // Aus Stereo mach Mono
                                k++;
                            }
                        }
                        for (int i = 0; i < b.Length; i++)
                        {
                            b[i] = (byte)((255 - b[i]) + 1);   // 2er Komplement
                        }
                        k = 0;
                        byte[] c = new byte[b.Length / 2];
                        for (int i = 0; i + 1 < b.Length; i+=2)
                        {
                            c[k] = (byte)(b[i + 1] / 1);  // High-Byte nehmen
                            k++;
                        }
                        outputStream.Write(c, 0, c.Length);
                    }
                    outputStream.Flush();
                    outputStream.Close();

Habe mal 2 Beispieldateien drangehangen, die das Ergebnis zeigen.
Ist schon ein heftiger Schritt von 16Bit zu 8Bit.

Habe das ganz mal parallel in einem Programm gemacht und da kam ich auf
ein ähnliches Ergebnis.

Meint ihr die Umwandlung kann so stimmen? Oder stimmt da etwas mit dem
Rauschen noch nicht?
 

Anhänge

  • Krombacher.mp3
    354,8 KB · Aufrufe: 13
  • Krombacher8BitMono.mp3
    176,9 KB · Aufrufe: 11

Muepe32

Erfahrenes Mitglied
Wäre es von der Idee her nicht besser, wenn du den 16-Bit Wert vom Intervall 0-65535 auf das Intervall 0-255 (8 Bit) abbildest? Damit verlierst du lediglich Genauigkeit, nicht jedoch Toninformationen.
Also:
C#:
ushort sample = samples[i];
byte byteSample = (byte)((sample / 65535.0f) * 255.0f);

Habe schon länger nichts mehr mit Audio gemacht, aber meiner Meinung nach sollte das eher zum Ziel führen.
 

Neue Beiträge