Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
ITADataSources
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
0
Merge Requests
0
Requirements
Requirements
List
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Analytics
Analytics
Code Review
Insights
Issue
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Institute of Technical Acoustics (ITA)
ITADataSources
Commits
f8bc3cb5
Commit
f8bc3cb5
authored
Nov 28, 2016
by
Dipl.-Ing. Jonas Stienen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Testing and updating ita data sink (write to buffer / audio file)
parent
3992ffe3
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
99 additions
and
80 deletions
+99
-80
include/ITABufferDataSink.h
include/ITABufferDataSink.h
+11
-13
src/ITABufferDataSink.cpp
src/ITABufferDataSink.cpp
+55
-51
tests/ITAPortaudioTests/ITAPortaudioInterfaceRecorder.cpp
tests/ITAPortaudioTests/ITAPortaudioInterfaceRecorder.cpp
+33
-16
No files found.
include/ITABufferDataSink.h
View file @
f8bc3cb5
...
...
@@ -38,12 +38,13 @@ class ITADatasource;
* welche die Audiodaten in eine Datei schreibt. Der Datentransfer muss
* selbst initiiert werden.
*/
class
ITA_DATA_SOURCES_API
ITABufferDatasink
{
class
ITA_DATA_SOURCES_API
ITABufferDataSink
{
public:
//! Konstruktor (Eigene Pufferverwaltung)
/**
* Dieser Konstruktor erzeugt eine Puffer-Datensenke. Die Puffer zum Speichern
* der Audiodaten werden bei diesem Konstruktor selbst erzeugt und von der
* der Audiodaten werden bei diesem Konstruktor selbst erzeugt und von der
* Datenquelle verwaltet. Mit dem Aufruf des Destruktors werden die Puffer
* freigeben. Die Pufferzeiger knnen mit der Methode GetBuffers() abgerufen werden.
*
...
...
@@ -52,8 +53,7 @@ public:
*
* \note Bei Fehlern werden ITAExceptions aufgelst.
*/
ITABufferDatasink
(
ITADatasource
*
pdsSource
,
unsigned
int
uiBuffersize
);
ITABufferDataSink
(
ITADatasource
*
pdsSource
,
int
uiBuffersize
);
//! Konstruktor (Fremdverwaltete Puffer)
/**
...
...
@@ -66,24 +66,22 @@ public:
*
* \note Bei Fehlern werden ITAExceptions aufgelst.
*/
ITABufferDatasink
(
ITADatasource
*
pdsSource
,
std
::
vector
<
float
*>
vpfBuffer
,
unsigned
int
uiBuffersize
);
ITABufferDataSink
(
ITADatasource
*
pdsSource
,
std
::
vector
<
float
*
>
vpfBuffer
,
int
uiBuffersize
);
//! Destruktor
virtual
~
ITABufferData
s
ink
();
virtual
~
ITABufferData
S
ink
();
//! Puffergre [Anzahl Samples] zurckgeben
unsigned
int
GetBuffersize
()
const
;
int
GetBuffersize
()
const
;
//! Pufferzeiger zurckgeben
std
::
vector
<
float
*
>
GetBuffers
()
const
;
std
::
vector
<
float
*
>
GetBuffers
()
const
;
//! Schreibposition in den Puffern zurckgeben
unsigned
int
GetWriteCursor
()
const
;
//! Schreibposition in den Puffern setzen
void
SetWriteCursor
(
unsigned
int
uiWriteCursor
);
void
SetWriteCursor
(
unsigned
int
uiWriteCursor
);
//! Audiodaten transferrieren
/**
...
...
@@ -91,9 +89,9 @@ public:
* und schreibt diese in die Audiodatei. Hierbei wird die Anzahl Samples
* auf das nchstgrere Vielfache der Blocklnge aufgerundet.
*/
void
Transfer
(
unsigned
int
uiSamples
);
void
Transfer
(
unsigned
int
uiSamples
);
private:
private:
ITADatasource
*
m_pdsSource
;
// Datenquelle
std
::
vector
<
float
*>
m_vpfBuffer
;
// Puffervektor
std
::
vector
<
const
float
*>
m_vpfBufferX
;
// Export-Puffervektor (const)
...
...
src/ITABufferDataSink.cpp
View file @
f8bc3cb5
...
...
@@ -11,92 +11,96 @@
#include <memory.h>
#endif
ITABufferData
sink
::
ITABufferDatasink
(
ITADatasource
*
pdsSource
,
unsigned
int
u
iBuffersize
)
:
m_pdsSource
(
pdsSource
)
,
m_vpfBuffer
(
pdsSource
->
GetNumberOfChannels
(),
NULL
)
,
m_vpfBufferX
(
pdsSource
->
GetNumberOfChannels
(),
NULL
)
,
m_uiBuffersize
(
u
iBuffersize
)
,
m_bManagedBuffer
(
true
)
ITABufferData
Sink
::
ITABufferDataSink
(
ITADatasource
*
pdsSource
,
int
iBuffersize
)
:
m_pdsSource
(
pdsSource
)
,
m_vpfBuffer
(
pdsSource
->
GetNumberOfChannels
(),
NULL
)
,
m_vpfBufferX
(
pdsSource
->
GetNumberOfChannels
(),
NULL
)
,
m_uiBuffersize
(
iBuffersize
)
,
m_bManagedBuffer
(
true
)
{
// Puffer erzeugen
for
(
unsigned
int
i
=
0
;
i
<
pdsSource
->
GetNumberOfChannels
();
i
++
)
{
m_vpfBuffer
[
i
]
=
fm_falloc
(
uiBuffersize
,
true
);
m_vpfBufferX
[
i
]
=
(
const
float
*
)
m_vpfBuffer
[
i
];
for
(
unsigned
int
i
=
0
;
i
<
pdsSource
->
GetNumberOfChannels
();
i
++
)
{
m_vpfBuffer
[
i
]
=
fm_falloc
(
iBuffersize
,
true
);
m_vpfBufferX
[
i
]
=
(
const
float
*
)
m_vpfBuffer
[
i
];
}
m_uiWriteCursor
=
0
;
}
ITABufferData
sink
::
ITABufferDatasink
(
ITADatasource
*
pdsSource
,
std
::
vector
<
float
*>
vpfBuffer
,
unsigned
int
u
iBuffersize
)
:
m_pdsSource
(
pdsSource
)
,
m_vpfBuffer
(
vpfBuffer
)
,
m_vpfBufferX
(
pdsSource
->
GetNumberOfChannels
(),
NULL
)
,
m_uiBuffersize
(
u
iBuffersize
)
,
m_bManagedBuffer
(
false
)
ITABufferData
Sink
::
ITABufferDataSink
(
ITADatasource
*
pdsSource
,
std
::
vector
<
float
*>
vpfBuffer
,
int
iBuffersize
)
:
m_pdsSource
(
pdsSource
)
,
m_vpfBuffer
(
vpfBuffer
)
,
m_vpfBufferX
(
pdsSource
->
GetNumberOfChannels
(),
NULL
)
,
m_uiBuffersize
(
iBuffersize
)
,
m_bManagedBuffer
(
false
)
{
// Parameter prfen
if
(
pdsSource
->
GetNumberOfChannels
()
!=
(
unsigned
int
)
vpfBuffer
.
size
()
)
ITA_EXCEPT1
(
INVALID_PARAMETER
,
"Number of buffers does not meet the datasource's number of channels"
);
if
(
pdsSource
->
GetNumberOfChannels
()
!=
(
unsigned
int
)
vpfBuffer
.
size
()
)
ITA_EXCEPT1
(
INVALID_PARAMETER
,
"Number of buffers does not meet the datasource's number of channels"
);
// Puffer erzeugen
for
(
unsigned
int
i
=
0
;
i
<
pdsSource
->
GetNumberOfChannels
();
i
++
)
m_vpfBufferX
[
i
]
=
(
const
float
*
)
m_vpfBuffer
[
i
];
for
(
unsigned
int
i
=
0
;
i
<
pdsSource
->
GetNumberOfChannels
();
i
++
)
m_vpfBufferX
[
i
]
=
(
const
float
*
)
m_vpfBuffer
[
i
];
m_uiWriteCursor
=
0
;
}
ITABufferData
sink
::~
ITABufferDatas
ink
()
{
if
(
m_bManagedBuffer
)
std
::
for_each
(
m_vpfBuffer
.
begin
(),
m_vpfBuffer
.
end
(),
fm_free
);
ITABufferData
Sink
::~
ITABufferDataS
ink
()
{
if
(
m_bManagedBuffer
)
std
::
for_each
(
m_vpfBuffer
.
begin
(),
m_vpfBuffer
.
end
(),
fm_free
);
}
unsigned
int
ITABufferDatasink
::
GetBuffersize
()
const
{
int
ITABufferDataSink
::
GetBuffersize
()
const
{
return
m_uiBuffersize
;
}
std
::
vector
<
float
*>
ITABufferData
s
ink
::
GetBuffers
()
const
{
std
::
vector
<
float
*>
ITABufferData
S
ink
::
GetBuffers
()
const
{
return
m_vpfBuffer
;
}
unsigned
int
ITABufferData
s
ink
::
GetWriteCursor
()
const
{
unsigned
int
ITABufferData
S
ink
::
GetWriteCursor
()
const
{
return
m_uiWriteCursor
;
}
void
ITABufferData
sink
::
SetWriteCursor
(
unsigned
int
uiWriteCursor
)
{
m_uiWriteCursor
=
(
std
::
min
)(
uiWriteCursor
,
m_uiBuffersize
);
void
ITABufferData
Sink
::
SetWriteCursor
(
unsigned
int
uiWriteCursor
)
{
m_uiWriteCursor
=
(
std
::
min
)(
uiWriteCursor
,
m_uiBuffersize
);
}
void
ITABufferDatasink
::
Transfer
(
unsigned
int
uiSamples
)
{
void
ITABufferDataSink
::
Transfer
(
unsigned
int
uiSamples
)
{
/*
* Hinweis: Auch wenn der Puffer schon vollgeschrieben wurde,
* so werden trotzdem die Daten von der Datenquelle
* so werden trotzdem die Daten von der Datenquelle
* geholt und dann ins Nirvana geworfen...
*/
if
(
m_pdsSource
)
{
// Anzahl der zu transferrierenden Blcke bestimmen
unsigned
int
b
=
m_pdsSource
->
GetBlocklength
();
unsigned
int
n
=
uprdivu
(
uiSamples
,
b
);
for
(
unsigned
int
i
=
0
;
i
<
n
;
i
++
)
{
// Anzahl der zu speichernden Samples bestimmen
unsigned
int
m
=
(
std
::
min
)(
m_uiBuffersize
-
m_uiWriteCursor
,
b
);
for
(
unsigned
int
j
=
0
;
j
<
m_pdsSource
->
GetNumberOfChannels
();
j
++
)
{
const
float
*
pfSrc
=
m_pdsSource
->
GetBlockPointer
(
j
,
&
m_siState
);
if
(
m
>
0
)
{
if
(
pfSrc
)
memcpy
(
m_vpfBuffer
[
j
]
+
m_uiWriteCursor
,
pfSrc
,
m
*
sizeof
(
float
));
else
memset
(
m_vpfBuffer
[
j
]
+
m_uiWriteCursor
,
0
,
m
*
sizeof
(
float
));
}
if
(
!
m_pdsSource
)
return
;
unsigned
int
n
=
uprdivu
(
uiSamples
,
m_pdsSource
->
GetBlocklength
()
);
// Number of block increments until data is completely transferred
// Iterate over blocks
for
(
unsigned
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
0
;
j
<
int
(
m_pdsSource
->
GetNumberOfChannels
()
);
j
++
)
{
const
float
*
pfSrc
=
m_pdsSource
->
GetBlockPointer
(
j
,
&
m_siState
);
unsigned
int
m
=
(
std
::
min
)(
m_uiBuffersize
-
m_uiWriteCursor
,
m_pdsSource
->
GetBlocklength
()
);
// One sample block or less
if
(
m
>
0
)
{
if
(
pfSrc
)
memcpy
(
m_vpfBuffer
[
j
]
+
m_uiWriteCursor
,
pfSrc
,
m
*
sizeof
(
float
)
);
else
memset
(
m_vpfBuffer
[
j
]
+
m_uiWriteCursor
,
0
,
m
*
sizeof
(
float
)
);
}
m_pdsSource
->
IncrementBlockPointer
();
m_uiWriteCursor
+=
m
;
m_siState
.
nSamples
+=
m_pdsSource
->
GetBlocklength
();
m_siState
.
dTimecode
=
(
double
)
(
m_siState
.
nSamples
)
/
m_pdsSource
->
GetSampleRate
();
m_siState
.
nSamples
+=
b
;
m_siState
.
dTimecode
=
(
double
)
(
m_siState
.
nSamples
)
/
m_pdsSource
->
GetSampleRate
();
m_pdsSource
->
IncrementBlockPointer
();
}
}
}
}
tests/ITAPortaudioTests/ITAPortaudioInterfaceRecorder.cpp
View file @
f8bc3cb5
// $Id: ITAPortaudioInterfaceRecorder.cpp 2333 2012-03-05 14:21:39Z stienen $
#include <ITAPortaudioInterface.h>
#include <ITADataSource.h>
//#include <ITADatasourceUtils.h>
#include <ITABufferDataSink.h>
#include <ITASampleFrame.h>
#include <iostream>
#include <string>
#include <ITADatasourceUtils.h>
#include <ITAPortaudioInterface.h>
#include <vector>
static
double
g_dSampleRate
=
44.1e3
;
static
int
g_iBlockSize
=
512
;
static
std
::
string
g_sOutputFileName
=
"ITAPA_Record.wav"
;
float
g_fRecordingTime
=
5
;
// Seconds
static
double
dSampleRate
=
44.1e3
;
static
int
iBlockSize
=
512
;
static
std
::
string
sOutputFileName
=
"ITAPA_Record.wav"
;
float
fRecordingTime
=
5
;
// Seconds
void
record
()
{
void
record
()
{
ITAPortaudioInterface
ITAPA
(
dSampleRate
,
iBlockSize
);
ITAPortaudioInterface
ITAPA
(
g_dSampleRate
,
g_iBlockSize
);
int
iInputDevice
=
ITAPA
.
GetDefaultInputDevice
();
//iInputDevice = 4;
ITAPortaudioInterface
::
ITA_PA_ERRORCODE
err
;
err
=
ITAPA
.
Initialize
(
iInputDevice
);
ITAPA
.
SetPlaybackEnabled
(
false
);
ITAPA
.
SetRecordEnabled
(
true
);
err
=
ITAPA
.
Initialize
(
iInputDevice
);
ITAPA
.
SetPlaybackEnabled
(
false
);
ITAPA
.
SetRecordEnabled
(
true
);
ITADatasource
*
pdsRecordDatasource
=
ITAPA
.
GetRecordDatasource
();
ITAPA
.
Open
();
unsigned
int
nRecordSamples
=
(
unsigned
int
)
(
5
*
g_dSampleRate
);
ITASampleFrame
sfRecordData
(
pdsRecordDatasource
->
GetNumberOfChannels
(),
nRecordSamples
,
true
);
std
::
vector
<
float
*
>
vpfRecordData
(
sfRecordData
.
channels
()
);
for
(
int
i
=
0
;
i
<
sfRecordData
.
channels
();
i
++
)
vpfRecordData
[
i
]
=
sfRecordData
[
i
].
data
();
ITAPA
.
Start
();
WriteFromDatasourceToFile
(
pdsRecordDatasource
,
sOutputFileName
,
(
unsigned
int
)(
5
*
dSampleRate
),
1.0
,
true
,
true
);
ITABufferDataSink
oBufferRec
(
pdsRecordDatasource
,
vpfRecordData
,
g_iBlockSize
);
oBufferRec
.
Transfer
(
nRecordSamples
);
//WriteFromDatasourceToFile( pdsRecordDatasource, sOutputFileName, (unsigned int)(5*g_dSampleRate), 1.0, true, true );
ITAPA
.
Stop
();
ITAPA
.
Close
();
ITAPA
.
Finalize
();
sfRecordData
.
Store
(
g_sOutputFileName
,
g_dSampleRate
);
return
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
,
char
**
)
{
std
::
cout
<<
"Starting recording ..."
<<
std
::
endl
;
record
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment