I am trying to build a DSP process in Matlab.
The ADC delivers uint16 data. This data should be filtered and processed. The filter works in the DSP with fixed point (fract16).
Should a transformation take place if I want to do work with the data Matlab? How to do it?
You can just treat the 16 bit unsigned fractional data as integers and then scale the data to floating point in the range 0.0..+1.0 prior to any processing. E.g.
data = data / 65535.0;
If the data is actually signed fractional (int16) then you would convert it to the range -1.0..+1.0 like this:
data = data / 32768.0;
Related
I have a file format called .ogpr (openGPR, a dead format used for Ground Radar data), I'm trying to read this file and convert it into a matrix using Matlab(R).
In the first part of file there is a JSON Header where are explained the characteristics of data acquisition (number of traces, position etc), and on the second part there are two different data blocks.
First block contains the 'real' GPR data and I know that they are formatted as:
Multibyte binary data are little-endian
Floating point binary data follow the IEEE 754 standard
Integer data follow the two’s complement encoding
I know also the total number of bytes and also the relative number of bytes for each single 'slice' (we have 512 samples * 10 channel * 3971 slices [x2 byte per sample]).
Furthermore: 'A Data Block of type Radar Volume stores a 3D array of radar Samples At the moment, each sample value is stored in a 16-bit signed integer. Each Sample value is in volts in the range [-20, 20].'
Second block contains geolocation infos.
I'd like to read and convert the Data Block from that codification but it ain't clear especially how many bytes break the data and how to convert them from that codification to number.
I tried to use this part of code:
bin_data = ogpr_data(48:(length(ogpr_data)-1),1);
writematrix(bin_data, 'bin_data.txt');
fileID = fopen('bin_data.txt', 'r', 'ieee-le');
format = 'uint16';
Data = fread(fileID, Inf, format);fclose(fileID)
Looks like your posted code is mixing text files and binary files. The writematrix( ) routine writes values as comma delimited text. Then you turn around and try to use fopen( ) and fread( ) to read this as a binary file in IEEE Little Endian format. These are two totally different things. You need to pick one format and use it consistently, either human readable comma delimited text files, or machine readable binary IEEE format files.
I'm reading an IMU on the arduino board with a s-function block in simulink by double or single data types though I just need 2 decimals precision as ("xyz.ab").I want to improve the performance with changing data types and wonder that;
is there a way to decrease the precision to 2 decimals in s-function block or by adding/using any other conversion blocks/codes in the simulink aside from using fixed-point tool?
For true fixed point transfer, fixed-point toolbox is the most general answer, as stated in Phil's comment.
However, to avoid toolbox use, you could also devise your own fix-point integer format and add a block that takes a floating point input and convert it into an integer format (and vice versa on the output).
E.g. If you know the range is 327.68 < var < 327.67 you could just define your float as an int16 divided by 10. In a matlab function block you would then just say
y=int16(u*100.0);
to convert the input to the S-function.
On the output it would be a reversal
y=double(u)/100.0;
(Eml/matlab function code can be avoided by using multiply, divide and convert blocks.)
However, be mindful of the bits available and that the scaling (*,/) operations is done on the floating point rather than the integer.
2^(nrOfBits-1)-1 shows you what range you can represent including signeage. For unsigned types uint8/16/32 the range is 2^(nrOfBits)-1. Then you use the scaling to fit the representable bit into your used floating point range. The scaled range divided by 2^nrOfBits will tell you what the resolution will be (how large are the steps).
You will need to scale the variables correspondingly on the Arduino side as well when you go to an integer interface of this type. (I'm assuming you have access to that code - if not it'd be hard to use any other interface than what is already provided)
Note that the intXX(doubleVar*scale) will always truncate the values to integer. If you need proper rounding you should also include the round function, e.g.:
int16(round(doubleVar*scale));
You don't need to use a base 10 scale, any scaling and offsets can be used, but it's easier to make out numbers manually if you keep to base 10 (i.e. 0.1 10.0 100.0 1000.0 etc.).
As a final note, if the Arduino code interface is floating point (single/double) and can't be changed to integer type; you will not get any speedup from rounding decimals since the full floating point is what will be is transferred anyway. Even if you do manage to reduce the data a bit using integers I suspect this might not give a huge speedup unless you transfer large amounts of data. The interface code will have a comparatively large overhead anyway.
Good luck with your project!
I am using MATLAB tool for extracting silence part from audio WAV files. After extracting silence part from audio, I want to save new audio as a WAV file.
For this process, I use 'audiowrite' function. However, the program warns to me with this message :
Warning: Data clipped when writing file.
I tried to add 'BitsPerSample' value with single file format(32 bit) and I dont take a message from program with this way. I saved audio files with 32 bit but WAV files should be 16 bit.
How can I fix this problem?
audiowrite(filename,y,fs,'BitsPerSample',32);
Note: I also normalized data and problem is same.
Thanks for your help!
UPDATE:
I want to normalize audio samples as mean 0 and standard deviation or variance 1.Thus, I use z-score normalization technique.
Also,y/max(abs(y)) method is normalized data between -1 and 1. However, mean and variance are not equal to 0 and 1 respectively. These techniques are normalized data with different way.
Actually, My question is that How can I save samples with z score normalization technique without data clipping?
Matlab's audiowrite uses different normalizations for different data types. So if you want to get 16bit audio wav file, you should normalize your data to the [-32768,32767] range and convert your data to int16 type:
y_normalized = intmax('int16') * y/(max(abs(y))*1.001);
audiowrite(filename, int16(y_normalized), fs)
Similarly, for float you should normalize your data to the [-1,+1] range :
y_normalized = y/(max(abs(y)));
audiowrite(filename, y_normalized, fs)
I need to read 4000 or more DICOM files. I have written the following code to read the files and store the data into a cell array so I can process them later. A single DICOM file contains 128 * 931 data. But once I execute the code it took more than 55 minutes to complete the iteration. Can someone point out to me the performance issue of the following code?
% read the file information form the disk to memory
readFile=dir('d:\images','*.dcm');
for i=1:4000
% Read the information form the dicom files in to arrays
data{i}=dicomread(readFile(i).name);
info{i}=dicominfo(readFile(i).name);
data_double{i}=double(data{1,i}); % convert 16 bit data into double
first_chip{i}=data_double{1,i}(1:129,1:129); % extracting first chip data into an array
end
You are reading 128*931*4000 pixels into memory (assuming 16-bit values, that's nearly 1 GB), converting that to doubles (4 GB) and extracting a region (129*129*4000*8 = 0.5 GB). You are keeping all three of these copies, which is a terrible amount of data! Try not keeping all that data around:
readFile = dir('d:\images','*.dcm');
first_chip = cell(size(readFile));
info = cell(size(readFile));
for ii = 1:numel(readFile)
info{ii} = dicominfo(readFile(ii).name);
data = dicomread(info{ii});
data = (1:129,1:129); % extracting first chip data
first_chip{ii} = double(data); % convert 16 bit data into double
end
Here, I have pre-allocated the first_chip and info arrays. If you don't do this, the arrays will be re-allocated every time you add an element, causing expensive copies. I have also extracted the ROI first, then converted to double, as suggested by Rahul in his answer. Finally, I am re-using the DICOM info structure to read the file. I don't know if this makes a big difference in speed, but it saves the dicomread function some effort.
But note that this process will still take a considerable amount of time. Reading DICOM files is complex, and takes time. I suggest you read them all in once, then save the first_chip and info cell arrays into a MAT-file, which will be a lot faster to read in at a later time.
You can run the profiler to check which part of the code is taking up most of the time! But as far as it looks to me is that its your iteration size & the time taken is very much genuine. You could try and use parallel computing ( parfor loop) if you have a multicore processor, that should decrease the runtime significantly depending upon the number of cores that you have.
One suggestion would be to exctract the 'first chip data' first and then convert it to double, as the conversion process takes a significant amount of time.
I am trying to convert an analog value to a digital value (8 bit A/D converter, input range 0-5V ).
I have used the formula (input*255/5) to convert to digital, then i have used digital to binary vi to convert this digital value to 8 bits.
The problem here is the data type mismatch between my output from the formula, which is a double data type and the input of the vi which is a digital data type, so how to solve this problem ? Thank you in advance
The digital data you mention is On/OFF. The example below illustrates the type of data that is entered and output from digital to binary.vi
On the left hand side is three samples of digital data in continuous signal format from three separate sources, (signal 0, signal 1, signal 2).
The first sample gives binary 2 (010). As you can see this would be not be of any use for a single signal.
If you still want to do the above, you could use DWDT Boolean Array to Digital as illustrated below: