В этом примере показано, как создать и использовать два различных Системных объекта, чтобы упростить потоковую передачу данных в и из MATLAB: dspdemo.TextFileReader
и dspdemo.TextFileWriter
.
Объекты, обсужденные в этом примере, обращаются ко многим реалистическим вариантам использования, и они могут быть настроены, чтобы достигнуть усовершенствованных и более специализированных задач.
В этом примере показано, как создать и использовать новые типы Системных объектов для чтения файла и записи. Внутренне, эти Системные объекты используют стандартные низкоуровневые функции ввода-вывода файлов, доступные в MATLAB (например, fscanf
fprintf
fread
fwrite
). Путем абстракции далеко большинства деталей использования тех функций, они стремятся делать задачу из чтения и записи переданных потоком данных более простой и более эффективной.
Этот пример включает использование многих усовершенствованных построений, чтобы создать Системные объекты. Для более основного введения в объекты авторской системы обратитесь к примерам в разделе Define New System Objects документации DSP System Toolbox.
Системные объекты являются классами MATLAB, которые выводят из matlab.System
. В результате Системные объекты, все наследовали общий открытый интерфейс, который включает следующие стандартные методы:
setup
- инициализировать объект, обычно в начале симуляции
reset
- очистить внутреннее состояние объекта, возвращая его его состоянию постинициализации по умолчанию
step
- выполнить базовую функциональность объекта, опционально принимая некоторый вход и/или возвращая некоторый выходной параметр
release
- высвобождать любые средства (например, память, оборудование, или специфичный для ОС) используемый внутренне объектом
Когда вы создаете новые виды Системных объектов, вы обеспечиваете определенные реализации для всех предыдущих методов, чтобы определить его поведение.
В этом примере мы обсуждаем внутреннюю структуру и использование следующих двух Системных объектов:
dspdemo.TextFileReader
Все Системные объекты в предыдущем списке совместно используют общую структуру. Например, dspdemo.TextFileReader
включает следующие разделы
1. Оператор определения класса, который подразумевает этот класс, выведен из обоих matlab.System
и matlab.system.mixin.FiniteSource
.
classdef TextFileReader < matlab.System & matlab.system.mixin.FiniteSource
matlab.System
требуется и базовый класс для всех Системных объектов
matlab.system.mixin.FiniteSource
указывает, что этот класс является источником сигнала с конечным числом выборок данных. Это подразумевает, что в дополнение к обычному интерфейсу Системный объект также отсоединит метод isDone. Когда isDone возвращает true, объект достиг конца доступных данных.
2. Много публичных свойств. В этом случае два являются ненастраиваемыми (они не могут быть изменены после первого вызова шага) и у всех есть значение по умолчанию. Значения по умолчанию присвоены соответствующим свойствам, когда ничто иное не задано пользователем. Публичные свойства могут быть изменены пользователем, чтобы настроить поведение объекта к его конкретному приложению.
properties (Nontunable) Filename = 'tempfile.txt' HeaderLines = 4 end
properties DataFormat = '%g' Delimiter = ',' SamplesPerFrame = 1024 PlayCount = 1 end
3. Много частных свойств. Они не отображаются пользователю и могут служить многим целям, включая
Держаться за значения вычисляло только иногда (например, во время инициализации, когда setup
называется или когда step
называется впервые), и затем использованный последующими вызовами step
. Это может сохранить перевычисление их во времени выполнения, и следовательно улучшать производительность базовой функциональности
Задавать внутреннее состояние объекта. Например, pNumEofReached
хранит число раз, что индикатор конца файла был достигнут
properties(Access = private) pFID = -1 pNumChannels pLineFormat pNumEofReached = 0 end
4. Конструктор. Это называется когда новый экземпляр dspdemo.TextDataReader
создается пользователем. Вызов метода setProperties
в конструкторе позволяет пользователям устанавливать свойства объекта путем обеспечения пар "имя-значение" при конструкции.
methods function obj = TextFileReader(varargin) setProperties(obj, nargin, varargin{:}); end end
5. Много переопределенных методов от matlab.System
базовый класс. Открытые методы, характерные для всех Системных объектов, у каждого есть соответствующие защищенные методы, которые они вызывают внутренне. Имена этих защищенных методов все включают Impl
постфикс. Они могут быть реализованы при определении класса, чтобы программировать определенное поведение конкретного Системного объекта.
Для получения дополнительной информации о соответствии между стандартными открытыми методами и их внутренними реализациями, обратитесь к Синхронизации Методов.
Например, конкретные методы внедрения, которые заменены для dspdemo.TextFileReader
setupImpl
resetImpl
stepImpl
releaseImpl
isDoneImpl
processTunedPropertiesImpl
loadObjectImpl
saveObjectImpl
6. Много закрытых методов. Эти методы только доступны из других методов того же класса. Они могут использоваться, чтобы сделать остальную часть кода более читаемой. Они могут также улучшить возможность многократного использования кода путем группировки в соответствии с отдельным кодом стандартных программ, который используется многократно в различных частях класса.
Код, который следует, дает простую демонстрацию того, как эти новые объекты могли использоваться. Следующие задачи показывают
Создайте текстовый файл, содержащий выборки двух различных синусоидальных сигналов с помощью dspdemo.TextFileWriter
Читайте из текстового файла с помощью dspdemo.TextFileReader
и запишите во второй файл в двоичной форме, на этот раз с помощью dsp.BinaryFileWriter
Считайте выборки сигнала циклически из нового двоичного файла с помощью dsp.BinaryFileReader
, и анализируйте результаты графически.
Чтобы запуститься, новый текстовый файл создается, чтобы сохранить два синусоидальных сигнала частотами 50 Гц и 60 Гц, соответственно. Для каждого сигнала хранимые данные будут состоять из 800 выборок на уровне выборки 8 кГц.
Следующее готовит данные
% Create data samples fs = 8000; tmax = 0.1; t = (0:1/fs:tmax-1/fs)'; N = length(t); f = [50,60]; data = sin(2*pi*t*f); % Optionally, form a header string to describe the data in a readable way % for future use fileheader = sprintf(['The following contains %d samples of two ',... 'sinusoids,\nwith frequencies %d Hz and %d Hz and a sample rate of',... ' %d kHz\n\n'], N, f(1),f(2),fs/1000);
Чтобы сохранить сигнал к текстовому файлу, создайте экземпляр средства записи текстового файла. Конструктор dspdemo.TextFileWriter
нуждается в имени конечного файла и некоторых дополнительных параметров, которые могут быть переданы в как пары "имя-значение".
TxtWriter = dspdemo.TextFileWriter('Filename','sinewaves.txt',... 'Header',fileheader) %#ok<NOPTS>
TxtWriter = dspdemo.TextFileWriter with properties: Filename: 'sinewaves.txt' Header: 'The following contains 800 samples of two sinusoids,...' DataFormat: '%.18g' Delimiter: ','
dspdemo.TextFileWriter
записывает данные к разделенным от разделителя ASCII-файлам. Его публичные свойства включают следующее
Filename
: имя файла, который будет записан. Если файл с этим именем уже существует, это перезаписывается. Когда операции запускаются, объект начинает запись к файлу сразу после заголовка - это затем добавляет новые данные в каждом последующем вызове шага, пока это не выпущено. Вызов сброса продолжает писать с начала файла.
Header
: символьная строка, часто состоящая из нескольких линий и отключенная символом новой строки (\n
). Это задано пользователем и может быть изменено, чтобы встроить человекочитаемую информацию, которая описывает фактические данные.
DataFormat
: формат раньше хранил каждую выборку данных. Это может принять любое значение, присваиваемое как Спецификатор Преобразования в formatSpec
строка, используемая встроенной функцией MATLAB fprintf
. DataFormat
применяется ко всем каналам, записанным в файл. Значением по умолчанию для этого свойства является '%.18g'
, который позволяет сохранять данные с плавающей запятой двойной точности в полной точности.
Delimiter
: символ раньше разделял выборки от различных каналов одновременно момент. Каждая линия записанных карт файлов к моменту времени, и это включает столько же выборок сколько количество каналов, обеспеченных, как введено (т.е. количество столбцов в матричном входе передало step
).
Записать все доступные данные в файл, один вызов step
может использоваться можно следующим образом
% Write to file with data as input % Note: |TxtWriter(data)| is equivalent to |step(TxtWriter, data)| TxtWriter(data) % Release control of file release(TxtWriter)
Данные теперь хранимы в новом файле. Чтобы смотреть файл визуально вводят edit('sinewaves.txt')
. Из-за заголовка обратите внимание, что данные запускаются на линии 4, после 3 линий заголовка.
В этом простом случае мала длина целого сигнала, и это соответствует удобно на системной памяти. Поэтому данные могут быть созданы целиком и записаны в файл на одном шаге, как только показано.
Существуют случаи, когда этот подход не возможен или практичен. Например, данные могут быть слишком большими, чтобы поместиться в одну переменную MATLAB (т.е. слишком большой, чтобы соответствовать на системной памяти), или это может быть создано циклически в цикле или передано потоком в MATLAB из внешнего источника. Во всех этих случаях может быть удобно передать данные потоком в файл при помощи подхода, похожего на следующее
% Use a streamed sine wave generator to create a frame of data per step frameLength = 32; SineWave = dsp.SineWave('Frequency',[50,60], 'SampleRate', fs, ... 'SamplesPerFrame', frameLength); % Run the desired number of iterations to create the data and store it into % the file tmax = 10; % Write more data in this scenario t = (0:1/fs:tmax-1/fs)'; N = length(t); data = sin(2*pi*t*f); numCycles = N/frameLength; for k = 1:numCycles dataFrame = SineWave(); TxtWriter(dataFrame) end % Release control of file and sine wave generator release(TxtWriter) release(SineWave)
Следующий шаг состоит в чтении данных из недавно созданного файла и записи его в новый двоичный файл.
Чтобы читать из текстового файла, создайте экземпляр dspdemo.TextFileReader
.
% Create a text file reader TxtReader = dspdemo.TextFileReader('Filename','sinewaves.txt',... 'HeaderLines',3,'SamplesPerFrame',frameLength) %#ok<NOPTS>
TxtReader = dspdemo.TextFileReader with properties: Filename: 'sinewaves.txt' HeaderLines: 3 DataFormat: '%g' Delimiter: ',' SamplesPerFrame: 32 PlayCount: 1
dspdemo.TextFileReader
считывает числовые данные из разделенных от разделителя ASCII-файлов. Его свойства похожи на те из dspdemo.TextFileWriter
. Некоторые различия следуют
HeaderLines
получает количество линий, используемых заголовком в файле, заданном в Filename
. Первый вызов step
начинает читать из номера строки HeaderLines+1
. Последующие вызовы step
продолжите читать из линии сразу после ранее прочитанной строки. Вызов reset
продолжит читать из линии HeaderLines+1
.
Delimiter
снова символ, используемый, чтобы разделить выборки от различных каналов одновременно момент. В этом случае это также используется, чтобы определить количество каналов данных, сохраненных в файле: когда step
сначала называется, числа объектов количество Delimiter
символы в линии HeaderLines+1
, скажите numDel
; это затем принимает в течение каждого раза момент, это должно считать numChan = numDel+1
числовые значения с форматом DataFormat
. Матрица, возвращенная шагом, имеет размер SamplesPerFrame
x numChan
.
SamplesPerFrame
количество строк, прочитанных каждым вызовом step
, т.е. количество строк матрицы, возвращенной, как выведено. Когда последние доступные строки данных достигнуты, это может произойти, что они - меньше, чем необходимый SamplesPerFrame
. В этом случае доступные данные дополнены нулями, чтобы получить матрицу размера SamplesPerFrame
x numChan
. Если все данные считаны, шаг просто возвращает zeros(SamplesPerFrame,numChan)
до reset
или release
называется.
PlayCount
число раз, данные в файле считаны циклически. Если объект достигает конца файла, и файл еще не был считан неоднократно равный PlayCount
, чтение резюме с начала данных (т.е. линия HeaderLines+1
). Если последние линии файла не обеспечивают достаточно выборок, чтобы сформировать полную выходную матрицу размера SamplesPerFrame
x numChan
, затем система координат завершается с помощью исходных данных. Если файл является чтением PlayCount
времена, выходная матрица, возвращенная шагом, заполнены нулями и всеми вызовами isDone
возвратите true, если не сброшено, или релиз называется. Циклично выполняться через доступные данные неопределенно, PlayCount
может быть установлен в Inf
.
Чтобы записать в новый двоичный файл, создайте экземпляр dsp.BinaryFileWriter
BinWriter = dsp.BinaryFileWriter('Filename','sinewaves.bin',... 'HeaderStructure',struct('Info',fileheader));
Данные передали как вход dsp.BinaryFileWriter
хранится с помощью его собственного типа данных. Например, вход с плавающей точкой с двойной точностью будет использовать 8 байтов за выборку. Выборки данных хранятся в порядке времени, и чередованы несколько каналов. Как следствие входные матрицы передали step
добавлены к файлу с помощью упорядоченного по строкам подхода (т.е. первая строка хранится сначала, слева направо, затем вторая строка, и так далее).
Чтобы передать данные из текстового файла в двоичный файл, более общий переданный потоком подход используется. Это также относится к контакту с очень большими файлами данных.
% Write binary data using single-precision floating point % Preallocate a data frame with |frameLength| rows and 2 columns dataFrame = zeros(frameLength,2,'single'); % Read from the text file and write to the binary file, whilst data is % present in the source text file. Notice how the method |isDone| is used % to control the execution of the while loop while(~isDone(TxtReader)) dataFrame(:) = TxtReader(); BinWriter(dataFrame) end % Release control of both files release(TxtReader) release(BinWriter)
sinewaves.bin
содержит целое число периодов для обеих синусоид, т.е. 500 периодов на уровне 50 Гц и 600 на уровне 60 Гц. Такие сигналы могут читаться циклически и использоваться, чтобы сгенерировать синусоиды произвольной длины. В последней части этой демонстрации dsp.BinaryFileReader
используется, чтобы сделать точно это. Когда данные считаны, эти две синусоиды визуализируются во временном интервале, и их продукт анализируется в частотном диапазоне.
frameLength = 1024; % Create an instance of a binary file reader BinReader = dsp.BinaryFileReader('Filename','sinewaves.bin',... 'HeaderStructure',struct('Info',zeros(1,numel(fileheader),'uint8')),... 'NumChannels',2,... 'DataType','single',... 'SamplesPerFrame',frameLength) %#ok<NOPTS> header = BinReader.readHeader.Info; % Display the header read from the file: char(header)
BinReader = dsp.BinaryFileReader with properties: Filename: 'sinewaves.bin' HeaderStructure: [1x1 struct] SamplesPerFrame: 1024 NumChannels: 2 DataType: 'single' IsDataComplex: false ans = 'The following contains 800 samples of two sinusoids, with frequencies 50 Hz and 60 Hz and a sample rate of 8 kHz '
Интерфейс dsp.BinaryFileReader
в основном очевидно. Следующее стоит заметить
HeaderStructure
задает ожидаемый заголовок в начале файла.
NumChannels
задает, сколько чередованных выборок ожидается в течение каждого раза момент. Это также определяет количество столбцов выходной матрицы, возвращенной объектом. Когда выполняется, объект возвращает матрицу размера SamplesPerFrame
x NumChannels
, сохраненный в файле упорядоченным по строкам способом.
Следующее создает компоненты, которые помогают с визуальным анализом переданных потоком сигналов, и во время и в частотном диапазоне
Для визуализации временного интервала, экземпляра dsp.TimeScope
создается. Это используется, чтобы построить все системы координат данных для обеих синусоид, когда они читаются из файла.
TimeScope = dsp.TimeScope('SampleRate',fs,'TimeSpan',frameLength/fs,... 'ShowGrid',true,'YLimits',[-1 1],'TimeSpanOverrunAction','Scroll');
Для визуализации частотного диапазона, экземпляра dsp.SpectrumAnalyzer
создается. Это используется, чтобы анализировать спектр продукта между этими двумя синусоидами, ожидая два тональных компонента в (60-50) Гц и (60+50) Гц, соответственно.
Поскольку отношение между частотами в сигнале и частоте дискретизации является очень низким, сигналы сначала подкошены фактором 16 с экземпляром dsp.SampleRateConverter
. Это понижает частоту дискретизации до 500 Гц и делает частотные составляющие из целевого более легко идентифицируемого использования сигнала стандартного спектрального анализа.
RateConverter = dsp.SampleRateConverter('InputSampleRate', 8000, ... 'OutputSampleRate', 500, 'Bandwidth', 100); % Note how a single spectral snapshot with the following settings % requires 16384 input samples, far more than the 800 actually stored in % the file SpectAnalyzer = dsp.SpectrumAnalyzer(... 'FrequencyResolutionMethod', 'WindowLength', 'WindowLength', 1024,... 'FFTLengthSource', 'Property', 'FFTLength', 2048, 'SampleRate',500,... 'PlotAsTwoSidedSpectrum', false, 'SpectralAverages', 16);
Следующий цикл с условием продолжения считывает данные из файла и визуализирует сигналы, когда они читаются. Это запускает в течение 10 минут ценность времени симуляции, независимо от фактического количества выборок в файле. Графики в двух переданной потоком визуализации совпадают с ожидаемым поведением.
simtime = 0; % Run the loop until the simulation time is less than 10*60 seconds while(simtime < 600) % Rewind file if there are no more new samples if isDone(BinReader) reset(BinReader) end % Read from binary file, 1024 samples per frame dataFrame = BinReader(); % Visualize a single frame of both channels in the time domain TimeScope(dataFrame) % Decimate the two channels down to a new sample rate of 500 Hz, % resulting in a new frame length of 64 samples dataDecimated = RateConverter(dataFrame); % Analyze the product of the two sine waves in the frequency domain, by % accumulating multiple data frames internally and updating the % visualization when ready SpectAnalyzer(prod(dataDecimated,2)) % Update value of simulation time elapsed simtime = simtime + frameLength/fs; end % Release control of files and scopes release(BinReader) release(RateConverter) release(TimeScope) release(SpectAnalyzer)
Этот пример проиллюстрировал, как создать и использовать Системные объекты, чтобы читать из и записать в файлы числовых данных. Все объекты используются (т.е. dspdemo.TextFileReader
, dspdemo.TextFileWriter
, dsp.BinaryFileReader
, и dsp.BinaryFileWriter
) может быть отредактирован, чтобы выполнить файл специального назначения читающие и пишущие операции.
Для получения дополнительной информации об объектах авторской системы для пользовательских алгоритмов см. Создание системных объектов.