Van qint16* naar qint16 vanuit QByteArray

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 17-09 19:09

LauPro

Prof Mierenneuke®

Topicstarter
Ik heb een applicatie die een wave-bestand uitleest:
C++:
1
QByteArray m_buffer = m_wavfile->readAll();
In deze QByteArray staat dus nu de volledige inhoud van de file. Nou wil ik echter deze file uit gaan lezen. Hij bestaat uit 16bit integers. De Wave-header heb ik een functie voor:
C++:
1
2
3
4
5
for (int i=0; i<m_wavfile->size() - (m_wavfile->headerLength() / m_format.channels() / 2); ++i) {
    const qint16* ptr = m_buffer.constData() + i * m_format.channels();
    const qint16 pcmValue = *ptr;
    // Gebruik pcmValue voor plotten
}
m_wavfile->headerLength() is een uint64 en moet dus gecast worden, op zich wel te doen. De bedoelig is dat er na de header de data van 1 spoor wordt uitgelezen. De snelheid is 44000 Hz, en het is dus 16 bit PCM.

Het bestandsformaat is als volgt:
code:
1
2
3
4
5
6
Header: lengte is headerLength()
int16 links (kanaal 1)
int16 recht (kanaal 2)
int16 links (kanaal 1)
int16 recht (kanaal 2)
..etc tot eof
Waar ik nu op stuk loop hoe ik een pointer krijg naar de m_buffer op bijvoorbeeld regel 2 en 4 uit het bovenstaande stukje.

m_buffer.constData() is een char, en ik wil er dus een qint16* uit krijgen zodat die gecast kan worden naar een qint16 waarmee ik kan plotten.

Iemand een schop in de juiste richting?

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 10:34

DataGhost

iPL dev

LauPro schreef op maandag 05 september 2011 @ 17:52:
m_buffer.constData() is een char
...o...kee hint: dat strookt niet echt met de rest van je code, that is, als die überhaupt werkt
en ik wil er dus een qint16* uit krijgen
??
zodat die [qint16*] gecast kan worden naar een qint16 waarmee ik kan plotten.
Dit gaat helemaal nergens over. Je bedoelt dereferencen en daarnaast wil je een offset ten opzichte van je buffer hebben om van daaruit een qint16 te maken.

Als ik je code zo zie heb je al stukjes werkend (al dan niet het meest logisch of efficiënt). Je vraag kom ik niet helemaal uit. Bedoel je dat je enkel 1 van de kanalen wilt uitlezen? Dan skip je toch gewoon elke even of oneven iteratie?

Verder is het over het algemeen handig om je variabelen minstens zo groot te maken als de velden in je bestandsformaat, helemaal in loopvariabelen anders kunnen er wel eens rare dingen gebeuren (bijvoorbeeld als je guardvariabele signed is, wat jouwe is, en je een bestand van meer dan 2 gigabyte te pakken hebt, wat niet helemaal ondenkbaar is tegenwoordig). Je kan niet zomaar in het wilde weg het een naar het ander casten.

[ Voor 26% gewijzigd door DataGhost op 05-09-2011 18:07 ]


Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 17-09 19:09

LauPro

Prof Mierenneuke®

Topicstarter
Ik zeg het verkeerd ;) :
C++:
1
const char * QByteArray::constData () const
Pointer naar een char dus.

Inderdaad, ik gooi wat termen door elkaar. Maar ik wil dus van bijvoorbeeld m_buffer.constData() + header + i een pointer hebben, en deze wil ik dan casten naar qint16...

Ik kan natuurlijk de twee waardes apart uitlezen als char en dan dmv bitwise operatoren tot een qint16 maken. Echter vraag ik mij af wat de 'nette' oplossing hier is.

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 10:34

DataGhost

iPL dev

Zodra je de juiste offset hebt kan je inderdaad casten naar het type wat je wilt hebben en in deze situatie is dat een goeie oplossing. Je vraag ging echter om het vinden van de offset, right?

[ Voor 4% gewijzigd door DataGhost op 05-09-2011 18:13 ]


Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 17-09 19:09

LauPro

Prof Mierenneuke®

Topicstarter
Jup, stel ik begin hier:
C++:
1
const qint16* ptr = reinterpret_cast<const qint16*>(m_buffer.constData());

Maar ik wil iets als:
C++:
1
const qint16* ptr = reinterpret_cast<const qint16*>(m_buffer.constData() + headerLength() + offset);
Echter dit laatste compiled niet...

De pointer zelfs is readonly, dus hoe krijg ik point naar een plek in die file...

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Als het niet compiled, dan krijg je een foutmelding die zegt waarom. Wat staat er in die melding?

Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 17-09 19:09

LauPro

Prof Mierenneuke®

Topicstarter
Ben een stapje verder:
C++:
1
2
3
4
const char *data = m_buffer.constData();
data+= m_wavfile->headerLength() + (i * m_format.channels() * 2);
const qint16* ptr = reinterpret_cast<const qint16*>(data);
const qint16 pcmValue = *ptr;
Alleen na iteratie +/- 1.200.000 krijg ik een segfault op die cast.

edit: de wave is zo'n 22 MB.

[ Voor 5% gewijzigd door LauPro op 05-09-2011 19:22 ]

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 18-09 21:46

Matis

Rubber Rocket

Volgens mij vergeet jij dat de sizeof quint16 niet 1 byte is.

Daarnaast begrijp ik echt niet wat je wilt proberen :?

[ Voor 61% gewijzigd door Matis op 05-09-2011 20:25 ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Probeer eens even goed na te denken over wat je wilt bereiken en wat je nu aan het doen bent, want het meeste wat je nu post gaat nergens over :) (no offense)

Ten eerste de header:
LauPro schreef op maandag 05 september 2011 @ 17:52:
Ik heb een applicatie die een wave-bestand uitleest:
C++:
1
2
3
4
5
for (int i=0; i<m_wavfile->size() - (m_wavfile->headerLength() / m_format.channels() / 2); ++i) {
    const qint16* ptr = m_buffer.constData() + i * m_format.channels();
    const qint16 pcmValue = *ptr;
    // Gebruik pcmValue voor plotten
}
De headerLength is neem ik aan de grootte van de totale header in bytes. Waarom deel je die door het aantal kanalen en nog eens door 2? De grootte van de header is niet afhankelijk van het aantal kanalen neem ik aan (in ieder geval niet in een normale wave file).

De PCM data begint op offset 0 + headerLength.
Als ik het goed begrijpt wil je deze data interpreteren als 16bit samples.

C++:
1
const qint16* ptr = reinterpret_cast<const qint16*>(m_buffer.constData() + headerLength());


zou moeten werken lijkt me. Nu heb je een pointer naar een qint16 op offset headerLength.

Om nu alle samples te plotten kun je door de rest van de data itereren(even uitgaand van mono):
C++:
1
2
3
4
5
for (int i=0; i < ((m_wavfile->size() - m_wavfile->headerLength()) / sizeof(qint16); ++i)
{
    qint16 pcmSample = *(ptr + i);
    // plot sample
}

Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 17-09 19:09

LauPro

Prof Mierenneuke®

Topicstarter
Ok, ik ben er achter. Het blijkt dat de QByteArray niet echt betrouwbaar is als je er meer dan 1 MB aan data in stopt. Ik lees nu de file in stukjes in van 16 KB en dan gaat het helemaal perfect.

Met de nodige debugging heb ik er een mooie waveform uitgekregen. Ik post nog wel wat screenshots.

Bedankt voor de hulp. En note to self: minder drinken tijdens het programmeren ;) .

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

LauPro schreef op dinsdag 06 september 2011 @ 03:39:
Ok, ik ben er achter. Het blijkt dat de QByteArray niet echt betrouwbaar is als je er meer dan 1 MB aan data in stopt.
Dat lijkt me heel sterk... Waarschijnlijk doe je gewoon iets verkeerd, lees je buiten je geheugen, maar valt dat niet op bij 16KB per keer omdat het nog steeds jouw geheugen is. (als je het nou nog over meer dan 2GB had...)

[ Voor 5% gewijzigd door Zoijar op 06-09-2011 08:06 ]


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

QByteArray is hardstikke 'betrouwbaar'. Nooit problemen mee gehad. Zoals eerder aangegeven: de code die je postte is niet juist.

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 18-09 21:46

Matis

Rubber Rocket

LauPro schreef op dinsdag 06 september 2011 @ 03:39:
Ok, ik ben er achter. Het blijkt dat de QByteArray niet echt betrouwbaar is als je er meer dan 1 MB aan data in stopt. Ik lees nu de file in stukjes in van 16 KB en dan gaat het helemaal perfect.

Met de nodige debugging heb ik er een mooie waveform uitgekregen. Ik post nog wel wat screenshots.

Bedankt voor de hulp. En note to self: minder drinken tijdens het programmeren ;) .
Ik mag het niet hopen, wij plempen full-frame SDI in een QByteArray. De omvang varieert van 6 tot 7,5MB en dat 50 keer per seconde.

Nooit problemen mee gehad.

If money talks then I'm a mime
If time is money then I'm out of time

Pagina: 1