QByteArray to Float Array
-
wrote on 9 May 2020, 11:59 last edited by
Hi,
I am fairly new to QT and C++; I have very good experience in C and HDL and its been a long time since I touched object orientated programming languages but I am slowly getting back into it.
Anyway I have a QT GUI working along with QCustomPlot , doing some networking and some file streaming. I can successfully capture the TCP packets from the network (8k packets) into a QByteArray and stream it into a file in binary and then read successfully in MATLAB with no packet loss or problems.
However I am now trying to get it to plot on screen in real-time using QCustomPlot,I have tested everything else and it is all ok, the only issue is that I can figure out how to convert a QByteArray which contains 2048 float samples into a single floating point number which can be sent for plotting on the QCPColourMap (in addition to this it accepts arguments of double). I am looking for the most efficient way to convert each sample in the ByteArray to floating point so that it can be plotted, custom functions will not be appropriate as the conversion at max capacity may be called at 245,000 times per second.
I have looked at various posts but I am not sure how I can adapt them as they assume that the entire QByteArray contains 1 floating samples (4 bytes) whereas my QByteArray over network contains 8192 Bytes. I have leant away of bit banging and forceful manipulation solutions, which look to be quite inefficient. I am certain that I am not the first person to have to do this also, if anyone has a better route regarding the QByteArray I am all ears.
Thanks in advance.
-
Hi thanks for the replies all,
I've given the code from @Bonnie and @Christian-Ehrlicher a go, but they seem to be spitting out constant values for the float "0.14425" or something like that, I am very confident my C program is not sending that as the data packet, since the Hex values in the packet sniffer do not show any obvious pattern. The full payloads are definitely getting there to the program and it is reporting a full 2048 sample packet. I will also need to convert the QCPColorMap to accept only float data at some point. The code that I am using is below:
while(tcpClient.bytesAvailable()){ data_in = tcpClient.read(PayloadSize); // 2048 samples int numSamples = data_in.size() / 4; for (int i=0; i<numSamples; ++i){ const float* ptrFloat = reinterpret_cast<const float*>(data_in.constData()); cout << i << " Float Val: " << *ptrFloat << endl; const double* ptrDouble = reinterpret_cast<const double*>(ptrFloat); cout << i << " Double Val: " << *ptrDouble << endl; colorMapRTI_1->data()->cellToCoord(i, 0, &x, &y); colorMapRTI_1->data()->setCell(i, 0, *ptrDouble); ptrFloat++; } ui->rti_1->replot(); colorMapRTI_1->rescaleDataRange(); } // end of while
Thanks everyone.
wrote on 9 May 2020, 17:23 last edited by Bonnie 5 Sept 2020, 17:43@Renegade243
Your code is always reading the first 4 bytes
Andconst double* ptrDouble = reinterpret_cast<const double*>(ptrFloat);
is definitely wrong in this case. Should change that to
while(tcpClient.bytesAvailable()){ data_in = tcpClient.read(PayloadSize); // 2048 samples int numSamples = data_in.size() / 4; const float* ptrFloat = reinterpret_cast<const float*>(data_in.constData()); for (int i=0; i<numSamples; ++i){ cout << i << " Float Val: " << *ptrFloat << endl; double readDouble = *ptrFloat ; cout << i << " Double Val: " << readDouble << endl; colorMapRTI_1->data()->cellToCoord(i, 0, &x, &y); colorMapRTI_1->data()->setCell(i, 0, readDouble); ptrFloat++; } ui->rti_1->replot(); colorMapRTI_1->rescaleDataRange(); } // end of while
-
Hi,
I am fairly new to QT and C++; I have very good experience in C and HDL and its been a long time since I touched object orientated programming languages but I am slowly getting back into it.
Anyway I have a QT GUI working along with QCustomPlot , doing some networking and some file streaming. I can successfully capture the TCP packets from the network (8k packets) into a QByteArray and stream it into a file in binary and then read successfully in MATLAB with no packet loss or problems.
However I am now trying to get it to plot on screen in real-time using QCustomPlot,I have tested everything else and it is all ok, the only issue is that I can figure out how to convert a QByteArray which contains 2048 float samples into a single floating point number which can be sent for plotting on the QCPColourMap (in addition to this it accepts arguments of double). I am looking for the most efficient way to convert each sample in the ByteArray to floating point so that it can be plotted, custom functions will not be appropriate as the conversion at max capacity may be called at 245,000 times per second.
I have looked at various posts but I am not sure how I can adapt them as they assume that the entire QByteArray contains 1 floating samples (4 bytes) whereas my QByteArray over network contains 8192 Bytes. I have leant away of bit banging and forceful manipulation solutions, which look to be quite inefficient. I am certain that I am not the first person to have to do this also, if anyone has a better route regarding the QByteArray I am all ears.
Thanks in advance.
wrote on 9 May 2020, 12:04 last edited by JonB 5 Sept 2020, 12:06@Renegade243 said in QByteArray to Float Array:
they assume that the entire QByteArray contains 1 floating samples (4 bytes) whereas my QByteArray over network contains 8192 Bytes
Not sure what you mean.
QByteArray QByteArray::mid(int pos, int len = -1)
gives you access to bytes in the middle of the array,const char *QByteArray::constData() const
gives you access to the raw data bytes, or you can just index into the array? Maybe I'm misunderstanding your question.... -
Hi and welcome to the forums.
So in your bytearray of 8192
how many values and how many bytes pr value ? -
wrote on 9 May 2020, 14:18 last edited by
Ok this might be some useful syntax, but how could I convert every 4 bytes into a float efficiently, I am surprised there is not a built in function which can do this ?
Thanks, I have 2048 float samples, 4 bytes per float in an 8K (8192 bytes) QByteArray received from TCP socket, like below:
QByteArray data_in; data_in = tcpClient.read(PayloadSize); // 2048 samples
and I need to get the samples out one by one to pass to the plotting function (argument accepts double but I can sort this after):
for (int i=0; i<2048; ++i){ colorMapRTI_1->data()->cellToCoord(i, 0, &x, &y); colorMapRTI_1->data()->setCell(i, 0, "double data sample"); }
Thanks for your time.
-
wrote on 9 May 2020, 15:06 last edited by Bonnie 5 Sept 2020, 15:35
Would this work? I'm using the Audio Input Example for reference.
const char *ptr = data_in.constData(); int numSamples = data_in.size() / 4; for (int i = 0; i < numSamples; ++i) { const float* ptrFloat = reinterpret_cast<const float*>(ptr); //use the float by: *ptrFloat ptr += 4; }
-
Would this work? I'm using the Audio Input Example for reference.
const char *ptr = data_in.constData(); int numSamples = data_in.size() / 4; for (int i = 0; i < numSamples; ++i) { const float* ptrFloat = reinterpret_cast<const float*>(ptr); //use the float by: *ptrFloat ptr += 4; }
@Bonnie no need to cast every time:
const float* ptrFloat = reinterpret_cast<const float*>(data_in.constData()); int numSamples = data_in.size() / 4; for (int i = 0; i < numSamples; ++i) { //use the float by: *ptrFloat ptrFloat++; }
-
wrote on 9 May 2020, 17:00 last edited by
Hi thanks for the replies all,
I've given the code from @Bonnie and @Christian-Ehrlicher a go, but they seem to be spitting out constant values for the float "0.14425" or something like that, I am very confident my C program is not sending that as the data packet, since the Hex values in the packet sniffer do not show any obvious pattern. The full payloads are definitely getting there to the program and it is reporting a full 2048 sample packet. I will also need to convert the QCPColorMap to accept only float data at some point. The code that I am using is below:
while(tcpClient.bytesAvailable()){ data_in = tcpClient.read(PayloadSize); // 2048 samples int numSamples = data_in.size() / 4; for (int i=0; i<numSamples; ++i){ const float* ptrFloat = reinterpret_cast<const float*>(data_in.constData()); cout << i << " Float Val: " << *ptrFloat << endl; const double* ptrDouble = reinterpret_cast<const double*>(ptrFloat); cout << i << " Double Val: " << *ptrDouble << endl; colorMapRTI_1->data()->cellToCoord(i, 0, &x, &y); colorMapRTI_1->data()->setCell(i, 0, *ptrDouble); ptrFloat++; } ui->rti_1->replot(); colorMapRTI_1->rescaleDataRange(); } // end of while
Thanks everyone.
-
Hi thanks for the replies all,
I've given the code from @Bonnie and @Christian-Ehrlicher a go, but they seem to be spitting out constant values for the float "0.14425" or something like that, I am very confident my C program is not sending that as the data packet, since the Hex values in the packet sniffer do not show any obvious pattern. The full payloads are definitely getting there to the program and it is reporting a full 2048 sample packet. I will also need to convert the QCPColorMap to accept only float data at some point. The code that I am using is below:
while(tcpClient.bytesAvailable()){ data_in = tcpClient.read(PayloadSize); // 2048 samples int numSamples = data_in.size() / 4; for (int i=0; i<numSamples; ++i){ const float* ptrFloat = reinterpret_cast<const float*>(data_in.constData()); cout << i << " Float Val: " << *ptrFloat << endl; const double* ptrDouble = reinterpret_cast<const double*>(ptrFloat); cout << i << " Double Val: " << *ptrDouble << endl; colorMapRTI_1->data()->cellToCoord(i, 0, &x, &y); colorMapRTI_1->data()->setCell(i, 0, *ptrDouble); ptrFloat++; } ui->rti_1->replot(); colorMapRTI_1->rescaleDataRange(); } // end of while
Thanks everyone.
wrote on 9 May 2020, 17:23 last edited by Bonnie 5 Sept 2020, 17:43@Renegade243
Your code is always reading the first 4 bytes
Andconst double* ptrDouble = reinterpret_cast<const double*>(ptrFloat);
is definitely wrong in this case. Should change that to
while(tcpClient.bytesAvailable()){ data_in = tcpClient.read(PayloadSize); // 2048 samples int numSamples = data_in.size() / 4; const float* ptrFloat = reinterpret_cast<const float*>(data_in.constData()); for (int i=0; i<numSamples; ++i){ cout << i << " Float Val: " << *ptrFloat << endl; double readDouble = *ptrFloat ; cout << i << " Double Val: " << readDouble << endl; colorMapRTI_1->data()->cellToCoord(i, 0, &x, &y); colorMapRTI_1->data()->setCell(i, 0, readDouble); ptrFloat++; } ui->rti_1->replot(); colorMapRTI_1->rescaleDataRange(); } // end of while
-
wrote on 9 May 2020, 18:09 last edited by Renegade243 5 Sept 2020, 18:09
Hi @Bonnie,
Thank you so much this did the trick, sorry for the late reply I was having fun playing with the streaming. This is really amazing thank you so much :)
Best Regards, Ren
1/9