using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace AudioPlayer.Tools {
public class Flac {
public String filename = "";
public String album = "";
public String artist = "";
public String title = "";
public int samplerate = 0;
public int minutes = 0;
public int seconds = 0;
public int bitcount = 0;
public Flac(String filename) {
this.filename = filename;
}
public bool readSamplerate() {
FileStream fin = new FileStream(this.filename, FileMode.Open, FileAccess.Read);
BinaryReader bin = new BinaryReader(fin);
// fLaC
byte[] headerSoll = { 0x66, 0x4C, 0x61, 0x43 };
byte[] header = new byte[headerSoll.Length];
header = bin.ReadBytes(header.Length);
for (int i = 0; i < headerSoll.Length; i++) {
if (headerSoll[i] != header[i]) {
Basis.ErrorMsg("Error, the audiofile is not a FLAC-File\r\n" + filename, "Error");
bin.Close();
fin.Close();
return false;
}
}
// samplerate
fin.Seek(0x12,SeekOrigin.Begin); // jump to the first byte of the sampleRate
byte[] samplerates = new byte[3];
//dummy1 = bin.ReadBytes(dummy1.Length);
samplerates = bin.ReadBytes(samplerates.Length); // adr: 12=byte[0], 13=byte[1], 14=byte[2] Bits: 12+13+ highbyte(14)
int b0 = samplerates[0];
int b1 = samplerates[1];
int b2 = samplerates[2];
samplerate = (b0 << 12) | (b1 << 4) | (b2 >> 4); // 192 kHz
//fin.Seek(0x12, SeekOrigin.Begin); // jump to the first byte of the sampleRate
byte[] samplescount = new byte[5];
samplescount = bin.ReadBytes(samplescount.Length); // 0x15 bis 0x19 von 0x15 nur die unteren bits
int sc0 = samplescount[0] & 0xF;
int sc1 = samplescount[1];
int sc2 = samplescount[2];
int sc3 = samplescount[3];
int sc4 = samplescount[4];
long scount = (sc0 << 32) | (sc1 << 24) | (sc2 << 16) | (sc3 << 8) | sc4;
long seconds = (long) (scount / samplerate);
this.minutes = (int)(seconds / 60.0);
this.seconds = (int)(seconds % 60);
byte[] channels = new byte[3];
channels = bin.ReadBytes(channels.Length); // 0x15 bis 0x19 von 0x15 nur die unteren bits
int bitcount0 = samplescount[0] >> 4; // F
int bitcount1 = samplerates[2] & 0xF; // 2
bitcount = (bitcount1<<4) | bitcount0;
// es sind nur 5 Bit zuständig
bitcount = bitcount >> 3;
/* https://xiph.org/flac/format.html#def_STREAMINFO
000 : get from STREAMINFO metadata block
001 : 8 bits per sample
010 : 12 bits per sample
011 : reserved
100 : 16 bits per sample
101 : 20 bits per sample
110 : 24 bits per sample
111 : reserved
*/
if (bitcount==5) {
bitcount = 16;
}
else if (bitcount == 6) {
bitcount = 24;
}
else {
Basis.ErrorMsg("Error to get the bits/sample\r\nPlease send an email to mwilhelm@hs-harz.de", "Error");
bitcount = -1;
}
bin.Close();
fin.Close();
return true;
}
/*
000 : get from STREAMINFO metadata block
001 : 8 bits per sample
010 : 12 bits per sample
011 : reserved
100 : 16 bits per sample
101 : 20 bits per sample
110 : 24 bits per sample
111 : reserved
* */
public bool readTexte() {
FileStream fin = new FileStream(this.filename, FileMode.Open, FileAccess.Read);
BinaryReader bin = new BinaryReader(fin);
// fLaC
byte[] headerSoll = { 0x66, 0x4C, 0x61, 0x43 };
byte[] header = new byte[headerSoll.Length];
header = bin.ReadBytes(header.Length);
for (int i1 = 0; i1 < headerSoll.Length; i1++) {
if (headerSoll[i1] != header[i1]) {
Basis.ErrorMsg("Error, the audiofile is not a FLAC-File\r\n" + filename, "Error");
bin.Close();
fin.Close();
return false;
}
}
fin.Seek(0, SeekOrigin.Begin);
byte[] bytes = new byte[10000];
bytes = bin.ReadBytes(bytes.Length);
// suche reference, dann ALBUMARTIST, ALBUM TITLE title
String searchItem = "reference";
bool reference = false;
int i = 0;
byte b = 0;
int positionReference = searchString(bytes, searchItem);
if (positionReference == -1) {
int p1 = searchString(bytes, "ALBUM=");
int p2 = searchString(bytes, "TITLE=");
int p3 = searchString(bytes, "title=");
int p4 = searchString(bytes, "ARTIST=");
if (p1 > 0 && p4 > 0 && (p2 > 0 || p3 > 0)) {
// nun gibt es doch einträge
bin.Close();
fin.Close();
// nun weiter siehe unten
}
else {
Basis.ErrorMsg("Error, the audiofile has not a reference-Block\r\n" + filename, "Error");
bin.Close();
fin.Close();
return false;
}
}
else {
positionReference += searchItem.Length; // Position auf das Byte nach der reference setzen
fin.Seek(positionReference, SeekOrigin.Begin);
bytes = bin.ReadBytes(bytes.Length); // nun nach reference lesen
bin.Close();
fin.Close();
}
album = "Please send an email to me!";
artist = "Please send an email to me!";
title = "Please send an email to me!";
searchItem = "ALBUM=";
int position = searchString(bytes, searchItem);
if (position == -1) {
searchItem = "Album=";
position = searchString(bytes, searchItem);
if (position == -1) {
searchItem = "album=";
position = searchString(bytes, searchItem);
if (position == -1) {
Basis.ErrorMsg("Error, the audiofile has no ALBUM-Text\r\n" + filename, "Error");
return false;
}
}
}
position += searchItem.Length;
album = searchTextUntilZero(bytes, position);
// -----------------------------------------
searchItem = "TITLE=";
position = searchString(bytes, searchItem);
if (position==-1) {
searchItem = "Title=";
position = searchString(bytes, searchItem);
if ((position == -1) ) {
searchItem = "title=";
position = searchString(bytes, searchItem);
if ((position == -1)) {
Basis.ErrorMsg("Error, the audiofile has no TITLE-Text\r\n" + filename, "Error");
return false;
}
}
}
if (position > 0) {
title = searchTextUntilZero(bytes, position);
}
searchItem = "ARTIST=";
position = searchString(bytes, searchItem);
if (position == -1) {
searchItem = "Artist=";
position = searchString(bytes, searchItem);
if ((position == -1)) {
searchItem = "artist=";
position = searchString(bytes, searchItem);
if ((position == -1)) {
Basis.ErrorMsg("Error, the audiofile has no Artist-Text\r\n" + filename, "Error");
return false;
}
}
}
if (position > 0) {
artist = searchTextUntilZero(bytes, position);
}
return true;
} // readTexte
private String searchTextUntilZero(byte[] bytes, int position) {
StringBuilder sb = new StringBuilder();
for (int i=position; i=32) {
if (bytes[i] == 0xC3 && bytes[i+1] == 0xBC) {
sb.Append("ü");
i++;
}
else {
sb.Append((char)bytes[i]);
}
}
}
}
return sb.ToString();
} // searchTextUntilZero
private int searchString(byte[] bytes, String searchItem) {
int position = -1;
byte[] searchItemBytes = new byte[searchItem.Length]; // Unicode !!
for (int i = 0; i < searchItem.Length; i++) {
searchItemBytes[i] = (byte)searchItem[i];
}
for(int i =0; i< bytes.Length;i++) {
if (bytes[i] == searchItemBytes[0]) {
// prüfe die Länge
bool okay = true;
for (int j = 0; j < searchItem.Length; j++) {
if (i + j < bytes.Length) {
if (bytes[i + j] != searchItemBytes[j]) { // error bei Paul Simon #14
okay = false;
break;
}
}
else {
break;
}
}
if (okay) {
position = i;
}
}
}
return position;
}
}
}
|