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
Compare Revisions
a33214010569cee76959ddc56e3e48326ef55bd5...b3f9d3d1f3077ff4745b67cc047d413201715d93
Source
b3f9d3d1f3077ff4745b67cc047d413201715d93
Select Git revision
...
Target
a33214010569cee76959ddc56e3e48326ef55bd5
Select Git revision
Compare
Commits (119)
39a0c4ef
added test for Portaudio
Feb 15, 2017
8abdf74e
protocol 2.0 not running
Feb 15, 2017
a7a4d983
Removing shell scripts that should not be in git
Feb 16, 2017
d212d013
Streaming Paras beim Start überarbeitet
Feb 16, 2017
bc14bb8e
setzt default Debug Parameter
Feb 16, 2017
671c79a6
bugfix
Feb 16, 2017
24cde1b3
protocol 2 not running
Feb 16, 2017
908d1e5a
add serverlogs
Feb 17, 2017
eac2e0db
protocol running, springt aber nciht in GetBlockpointer (portaudio)
Feb 17, 2017
a37247be
für 32 bit + serverLog update + bugfix ReadMessage
Feb 17, 2017
01cb7c2a
sendet jetzt bis buffer voll und horcht erst dann - not running
Feb 17, 2017
7ee2ae14
bugfixes deiconnect not running
Feb 20, 2017
ea17bf32
bugfixes server
Feb 20, 2017
21eb6780
bugfixes: probleme mit logger noch offen
Feb 20, 2017
17506775
bugfixes server
Feb 20, 2017
e941e65f
bugfix recivedByteTatal Error
Feb 21, 2017
e378f4a8
bugfix close connection + es werden immernoch zuviele daten geschickt, der...
Feb 21, 2017
a839b645
bugixes, running new protocol 2
Feb 21, 2017
f4c7c40d
bugfixes protocol 2 running server
Feb 21, 2017
acd7c91c
server kalkuliere mögliche freie samples (overrun gefahr) -> TODO target latency setzten
Feb 21, 2017
cb02e20d
versuch client sendet von selsbt buffer infos - not running
Feb 21, 2017
c1f56f7a
bugfix Server freebuffer selbst kalkulieren
Feb 21, 2017
62f95302
Reverting to branch with origin
Feb 22, 2017
44bb65cd
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Feb 22, 2017
f8cea23d
Merge remote-tracking branch 'remotes/origin/ba_2016_heimes' into develop
Feb 22, 2017
d7d9cda2
Fixing merge stuff
Feb 22, 2017
1bfecbc7
anpassung für latenz auf dem server - Client
Feb 22, 2017
0d9073a6
Fixing disconnect problems with client
Feb 22, 2017
6c4f4aa7
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Feb 22, 2017
e32b6da6
Resolving problems with git
Feb 22, 2017
26649fd2
Client-initialized close is accepted by server and client waits for...
Feb 22, 2017
f0ac824b
Re-adding stream log item push
Feb 22, 2017
4e81b87c
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Feb 22, 2017
261d2ace
puffer wird jetzt immer vollgeschireben, läuft
Mar 01, 2017
6171d862
wahl zwischen client und server beim plot
Mar 01, 2017
5cc9b42a
Client wartet nicht mehr, beide senden einfach => running, aber nicht...
Mar 01, 2017
ea4b58c1
bugfix
Mar 01, 2017
7f3de3ce
bugfixes
Mar 01, 2017
504b00bb
bugfix blocklänge server
Mar 01, 2017
677458e7
bugfixes
Mar 02, 2017
82be59b0
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 21, 2017
72011a7c
server kalkuliert selbst den Ringbuffer, Client gibt nur noch alle x sec bufferInfos an server
Mar 23, 2017
65752f4f
bugfixes
Mar 23, 2017
74604554
bugfixes server
Mar 23, 2017
05bd803e
server bugfix
Mar 24, 2017
a898d8fd
bugfix
Mar 24, 2017
4ac135c6
bugfixes
Mar 24, 2017
470a6db9
bugfix
Mar 24, 2017
9138f612
protocol Log added
Mar 27, 2017
09cdaa44
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 27, 2017
0ff78684
bugfix
Mar 27, 2017
3de3dab0
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 27, 2017
a11a0156
protokol log bugfix
Mar 27, 2017
f0bf059f
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 27, 2017
5fc5cf09
bugfix
Mar 27, 2017
aa50bf92
bugfix
Mar 27, 2017
6b4bb1b0
Cleaning up client test and fixing crash on failed connection
Mar 27, 2017
c5561a1d
Cleaning up NetAudio server test
Mar 27, 2017
db336c73
Switching to 64 blocks / 128 samples target latency (32 does not work for hammerfall dsp)
Mar 27, 2017
836ee756
Refactoring a lot for logging netaudio messages
Mar 27, 2017
bf81aade
Updating server logging base name setting for tests
Mar 27, 2017
bc6f5812
Finished logging refactoring
Mar 27, 2017
f841f8d3
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 27, 2017
01425b60
Updating net audio test (portaudio single instance over localhost)
Mar 27, 2017
33a76773
Adding missing ".log" extensions after base names
Mar 27, 2017
8785c0c4
Statistics for try-read access
Mar 27, 2017
d562e5ca
Refactoring. And fixing problem with ring buffer size in NetAudioStream...
Mar 27, 2017
44b290fe
Adapting and improving script to plot ITANetAudioTest logging output
Mar 28, 2017
1e4b20ab
Progress, now also ASIO available for NetAudio test.
Mar 28, 2017
e7d71ecd
Config tweaks for good test results
Mar 28, 2017
90a01fef
bugfixes logging
Mar 28, 2017
ed170e0f
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 28, 2017
fbe6a4d5
bugfixed logger
Mar 28, 2017
7468e80f
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 28, 2017
79a868df
server test paras einlesen
Mar 28, 2017
df4aa311
server sendet variable Blocklängen
Mar 29, 2017
a4a9fd6d
log datei serverblocklänge hinzugefügt
Mar 29, 2017
a10c1417
Fixing problems on destroctíon of netaudio instanes
Mar 29, 2017
8bc757bd
Merging server impl of NetAudio
Mar 29, 2017
32d65f52
Refactoring #1
Mar 29, 2017
dfea0f75
Refactoring #2
Mar 29, 2017
03ea1737
Refactoring #3
Mar 29, 2017
45cc77b6
Refactoring #4
Mar 29, 2017
960e909f
Adding debug switch for NetAudio server test
Mar 29, 2017
5c60efa2
bugfix
Mar 30, 2017
7a53b1a7
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 30, 2017
24913538
Adding switchens for UDP connection, not yet finished on UDP side, but TCP...
Mar 30, 2017
376eb96c
Updating some more interfaces and retrating default options where interface is...
Mar 30, 2017
5aa47a5a
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Mar 30, 2017
e54c7168
asio treiber im test hinzugefügt
Mar 30, 2017
be88dcb0
debuggen des fehlers mit der riesen größe für ankommende daten...
Mar 30, 2017
d8a9619f
Adding UDP test code, not running yet
Mar 31, 2017
3531b26a
debug auskommentiert
Mar 31, 2017
4289aaf0
bugfix server
Mar 31, 2017
fc01867c
correction factor für die schätzung des servers
Apr 03, 2017
eb656507
estimated corr factor selbst stezten, jetzt messen wie es aussieht
Apr 03, 2017
35a820a3
Fixing NetAudio try-read crash (was already receiving and processing next message)
Apr 03, 2017
5aceb84c
Changing test params
Apr 03, 2017
c2ba8c23
Merge branch 'ba_2016_heimes' of
https://git.rwth-aachen.de/ita/ITADataSources
into ba_2016_heimes
Apr 03, 2017
ecbe89dd
add serverCorrection factor
Apr 04, 2017
19 additional commits have been omitted to prevent performance issues.
Hide whitespace changes
Inline
Side-by-side
Showing
59 changed files
with
2678 additions
and
1367 deletions
+2678
-1367
CMakeLists.txt
CMakeLists.txt
+7
-8
include/ITANetAudioSampleServer.h
include/ITANetAudioSampleServer.h
+143
-0
include/ITANetAudioStream.h
include/ITANetAudioStream.h
+72
-46
include/ITANetAudioStreamingServer.h
include/ITANetAudioStreamingServer.h
+59
-34
include/ITAStreamInfo.h
include/ITAStreamInfo.h
+32
-15
include/ITAStreamPatchBay.h
include/ITAStreamPatchBay.h
+1
-1
src/ITAAsioInterface.cpp
src/ITAAsioInterface.cpp
+442
-374
src/ITABufferDataSink.cpp
src/ITABufferDataSink.cpp
+3
-1
src/ITADataSourceRealization.cpp
src/ITADataSourceRealization.cpp
+59
-58
src/ITADataSourceUtils.cpp
src/ITADataSourceUtils.cpp
+6
-2
src/ITAFileDataSink.cpp
src/ITAFileDataSink.cpp
+15
-7
src/ITANetAudioClient.cpp
src/ITANetAudioClient.cpp
+10
-6
src/ITANetAudioClient.h
src/ITANetAudioClient.h
+2
-2
src/ITANetAudioMessage.cpp
src/ITANetAudioMessage.cpp
+170
-46
src/ITANetAudioMessage.h
src/ITANetAudioMessage.h
+21
-4
src/ITANetAudioProtocol.cpp
src/ITANetAudioProtocol.cpp
+1
-1
src/ITANetAudioProtocol.h
src/ITANetAudioProtocol.h
+30
-12
src/ITANetAudioServer.cpp
src/ITANetAudioServer.cpp
+47
-20
src/ITANetAudioServer.h
src/ITANetAudioServer.h
+6
-5
src/ITANetAudioStream.cpp
src/ITANetAudioStream.cpp
+106
-129
src/ITANetAudioStreamingClient.cpp
src/ITANetAudioStreamingClient.cpp
+195
-75
src/ITANetAudioStreamingClient.h
src/ITANetAudioStreamingClient.h
+22
-13
src/ITANetAudioStreamingServer.cpp
src/ITANetAudioStreamingServer.cpp
+263
-59
src/ITAStreamPump.cpp
src/ITAStreamPump.cpp
+22
-12
tests/ITAPortaudioTests/ITAPortaudioInterfaceRecorder
tests/ITAPortaudioTests/ITAPortaudioInterfaceRecorder
+0
-0
tests/ITAPortaudioTests/set_path_for_ITAPortaudioInterfaceRecorder.sh
...taudioTests/set_path_for_ITAPortaudioInterfaceRecorder.sh
+0
-6
tests/ITAPortaudioTests/set_path_for_ITAPortaudioInterfaceTest.sh
...APortaudioTests/set_path_for_ITAPortaudioInterfaceTest.sh
+0
-6
tests/ITAPortaudioTests/set_path_for_ITAPortaudioMeasurementTest.sh
...ortaudioTests/set_path_for_ITAPortaudioMeasurementTest.sh
+0
-6
tests/NetAudio/CMakeLists.txt
tests/NetAudio/CMakeLists.txt
+31
-7
tests/NetAudio/CMakeLists.txt_
tests/NetAudio/CMakeLists.txt_
+0
-59
tests/NetAudio/ITANABufferServerTest
tests/NetAudio/ITANABufferServerTest
+0
-0
tests/NetAudio/ITANAPlayerTest
tests/NetAudio/ITANAPlayerTest
+0
-0
tests/NetAudio/ITANetAudioStreamingClientTest.cpp
tests/NetAudio/ITANetAudioStreamingClientTest.cpp
+80
-108
tests/NetAudio/ITANetAudioStreamingPortaudioClientTest.cpp
tests/NetAudio/ITANetAudioStreamingPortaudioClientTest.cpp
+76
-0
tests/NetAudio/ITANetAudioStreamingServerTest.cpp
tests/NetAudio/ITANetAudioStreamingServerTest.cpp
+84
-25
tests/NetAudio/ITANetAudioTest
tests/NetAudio/ITANetAudioTest
+0
-0
tests/NetAudio/ITANetAudioTest.cpp
tests/NetAudio/ITANetAudioTest.cpp
+185
-59
tests/NetAudio/NatLogUnderruns.m
tests/NetAudio/NatLogUnderruns.m
+61
-0
tests/NetAudio/NetAudioLog.m
tests/NetAudio/NetAudioLog.m
+80
-70
tests/NetAudio/NetAudioServerLog.m
tests/NetAudio/NetAudioServerLog.m
+125
-0
tests/NetAudio/NetLogLatency.m
tests/NetAudio/NetLogLatency.m
+67
-0
tests/NetAudio/set_path_for_ITANABufferServerTest.sh
tests/NetAudio/set_path_for_ITANABufferServerTest.sh
+0
-6
tests/NetAudio/set_path_for_ITANAPlayerTest.sh
tests/NetAudio/set_path_for_ITANAPlayerTest.sh
+0
-6
tests/NetAudio/set_path_for_ITANetAudioStreamingServerTest.sh
...s/NetAudio/set_path_for_ITANetAudioStreamingServerTest.sh
+0
-6
tests/NetAudio/set_path_for_ITANetAudioTest.sh
tests/NetAudio/set_path_for_ITANetAudioTest.sh
+0
-6
tests/VistaNetTest/ITAVistaNetClient
tests/VistaNetTest/ITAVistaNetClient
+0
-0
tests/VistaNetTest/ITAVistaNetServer
tests/VistaNetTest/ITAVistaNetServer
+0
-0
tests/VistaNetTest/ITAVistaNetTest
tests/VistaNetTest/ITAVistaNetTest
+0
-0
tests/VistaNetTest/VistaNetTest.cpp
tests/VistaNetTest/VistaNetTest.cpp
+155
-7
tests/VistaNetTest/set_path_for_ITAVistaNetClient.sh
tests/VistaNetTest/set_path_for_ITAVistaNetClient.sh
+0
-6
tests/VistaNetTest/set_path_for_ITAVistaNetServer.sh
tests/VistaNetTest/set_path_for_ITAVistaNetServer.sh
+0
-6
tests/VistaNetTest/set_path_for_ITAVistaNetTest.sh
tests/VistaNetTest/set_path_for_ITAVistaNetTest.sh
+0
-6
tests/set_path_for_BufferDataSourceTest.sh
tests/set_path_for_BufferDataSourceTest.sh
+0
-6
tests/set_path_for_DatasourceUtilsTest.sh
tests/set_path_for_DatasourceUtilsTest.sh
+0
-6
tests/set_path_for_FileDataSourceTest.sh
tests/set_path_for_FileDataSourceTest.sh
+0
-6
tests/set_path_for_PeakDetectorTest.sh
tests/set_path_for_PeakDetectorTest.sh
+0
-6
tests/set_path_for_StreamFunctionGeneratorTest.sh
tests/set_path_for_StreamFunctionGeneratorTest.sh
+0
-6
tests/set_path_for_StreamPatchbayTest.sh
tests/set_path_for_StreamPatchbayTest.sh
+0
-6
tests/set_path_for_StreamProbeTest.sh
tests/set_path_for_StreamProbeTest.sh
+0
-6
No files found.
CMakeLists.txt
View file @
b3f9d3d1
...
...
@@ -110,23 +110,22 @@ endif( )
if
(
ITA_DATA_SOURCES_WITH_NET_AUDIO
)
list
(
APPEND ITADataSourcesHeader
"include/ITANetAudioClient.h"
"include/ITANetAudioMessage.h"
"include/ITANetAudioProtocol.h"
"include/ITANetAudioServer.h"
"include/ITANetAudioStream.h"
"include/ITANetAudioS
treamingClient
.h"
"include/ITANetAudioS
ampleServer
.h"
"include/ITANetAudioStreamingServer.h"
"include/ITANetAudioStreamingClient.h"
)
list
(
APPEND ITADataSourcesSources
"src/ITANetAudioClient.cpp"
"src/ITANetAudioClient.h"
"src/ITANetAudioMessage.cpp"
"src/ITANetAudioProtocol.cpp"
"src/ITANetAudioMessage.h"
"src/ITANetAudioProtocol.h"
"src/ITANetAudioServer.cpp"
"src/ITANetAudioServer.h"
"src/ITANetAudioStream.cpp"
"src/ITANetAudioStreamingClient.cpp"
"src/ITANetAudioStreamingClient.h"
"src/ITANetAudioStreamingServer.cpp"
"src/ITANetAudioServer.cpp"
)
endif
(
)
...
...
include/ITANetAudioSampleServer.h
0 → 100644
View file @
b3f9d3d1
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef INCLUDE_WATCHER_ITA_NET_AUDIO_SAMPLE_SERVER
#define INCLUDE_WATCHER_ITA_NET_AUDIO_SAMPLE_SERVER
#include <ITADataSourcesDefinitions.h>
#include <ITANetAudioStreamingServer.h>
#include <ITADataSourceRealization.h>
//! Sample-generation class with abstract method for providing samples
/*
* This ready-to-use class helps to provide samples for a NetAudio streaming server with
* a single method for processing that has to be implemented ...
* ... just derive and implement Process() method. Have a look at Zero() method
* for exemplary usage of sample buffer.
*/
class
CITASampleProcessor
:
public
ITADatasourceRealization
{
public:
//! Create a sample processor with streaming parameters
/*
* @param[in] iNumChannels Channels provided
* @param[in] dSampleRate Audio processing sampling rate
* @param[in] iBlockLength Audio processing block length / buffer size
*/
inline
CITASampleProcessor
(
const
int
iNumChannels
,
const
double
dSampleRate
,
const
int
iBlockLength
)
:
ITADatasourceRealization
(
(
unsigned
int
)
(
iNumChannels
),
dSampleRate
,
(
unsigned
int
)
(
iBlockLength
)
)
{
m_vvfSampleBuffer
.
resize
(
iNumChannels
);
for
(
size_t
c
=
0
;
c
<
iNumChannels
;
c
++
)
m_vvfSampleBuffer
[
c
].
resize
(
iBlockLength
);
Zero
();
};
inline
~
CITASampleProcessor
()
{
};
//! Sets all channels and samples to zero
inline
void
Zero
()
{
/*
* Use this as an example how to work with the buffer structure.
*/
// Iterate over channels
for
(
size_t
c
=
0
;
c
<
m_vvfSampleBuffer
.
size
();
c
++
)
{
std
::
vector
<
float
>&
vfSingleChannelSampleBuffer
(
m_vvfSampleBuffer
[
c
]
);
// One channel
// Iterate over samples of channel
for
(
size_t
n
=
0
;
n
<
vfSingleChannelSampleBuffer
.
size
();
n
++
)
{
float
&
fSample
(
vfSingleChannelSampleBuffer
[
n
]
);
// One sample
fSample
=
0.0
f
;
// -> Manipulation
}
}
};
//! Process samples (overwrite this virtual method)
/**
* Method that is called in audio streaming context and requests
* to produce or copy audio samples into the internal buffer m_vvfSampleBuffer
*
* @param[in] pStreamInfo Information over streaming status, i.e. sample count and time stamp
*
*/
virtual
void
Process
(
const
ITAStreamInfo
*
pStreamInfo
)
=
0
;
protected:
std
::
vector
<
std
::
vector
<
float
>
>
m_vvfSampleBuffer
;
//!< Multi-channel sample buffer to be filled
private:
//! Delegate internal buffer to audio stream (ITADatasource)
inline
void
ProcessStream
(
const
ITAStreamInfo
*
pInfo
)
{
Process
(
pInfo
);
for
(
size_t
c
=
0
;
c
<
m_vvfSampleBuffer
.
size
();
c
++
)
{
float
*
pfData
=
GetWritePointer
(
(
unsigned
int
)
(
c
)
);
for
(
size_t
n
=
0
;
n
<
m_vvfSampleBuffer
[
c
].
size
();
n
++
)
pfData
[
n
]
=
m_vvfSampleBuffer
[
c
][
n
];
}
IncrementWritePointer
();
};
};
//! Network audio sample server (for providing samples via derived generator class)
/**
* Audio sample transmitter for a networked sample callback function that can connect via TCP/IP.
*
* @sa CITANetAudioStream CITANetAudioStreamingServer CITASampleProcessor
* @note not thread-safe
*/
class
CITANetAudioSampleServer
:
public
CITANetAudioStreamingServer
{
public:
inline
CITANetAudioSampleServer
(
CITASampleProcessor
*
pProcessor
)
:
m_pSampleProcessor
(
pProcessor
)
{
SetInputStream
(
m_pSampleProcessor
);
};
inline
~
CITANetAudioSampleServer
()
{};
private:
//! Prohibit public access to streaming context and delegate
inline
void
SetInputStream
(
ITADatasource
*
pDataSource
)
{
CITANetAudioStreamingServer
::
SetInputStream
(
pDataSource
);
};
//! Prohibit public access to streaming context and delegate
inline
ITADatasource
*
GetInputStream
()
const
{
return
CITANetAudioStreamingServer
::
GetInputStream
();
};
CITASampleProcessor
*
m_pSampleProcessor
;
//!< Callback / sample processor
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_SAMPLE_SERVER
include/ITANetAudioStream.h
View file @
b3f9d3d1
...
...
@@ -26,9 +26,6 @@
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
using
namespace
std
;
class
CITANetAudioStreamingClient
;
...
...
@@ -38,7 +35,7 @@ class ITABufferedDataLoggerImplAudio;
//! Network audio stream
/**
* Audio streaming for a signal source that is connected via TCP/IP.
* Audio streaming for a signal source that is connected via TCP/IP
or UDP
.
* The network audio stream behaves like a client and receives samples
* from a network audio stream server, CITANetAudioStreamingSearver.
*
...
...
@@ -46,11 +43,13 @@ class ITABufferedDataLoggerImplAudio;
* block the streaming processing, because it is decoupled from the
* network connection and forwards samples from an internal ring buffer.
* If the buffer runs out of samples, zeros will be return. If the buffer
* overruns, the sample server will be suspende
b
by blocking the network
* overruns, the sample server will be suspende
d
by blocking the network
* data flow.
*
* Latency can be managed by either providing a small ring buffer or
* oversizing the ring buffer and requesting a target latency.
* Latency can be managed by either providing a small ring buffer and
* constantly filling it uo, or by oversizing the internal ring buffer
* only pushing samples to meet a target latency. This has to be
* implemented by the server.
*
* \note not thread-safe
*/
...
...
@@ -58,7 +57,21 @@ class ITA_DATA_SOURCES_API CITANetAudioStream : public ITADatasource
{
public:
//! Constructor of a network audio stream
CITANetAudioStream
(
int
iChannels
,
double
dSamplingRate
,
int
iBufferSize
,
int
iRingBufferCapacity
=
2048
);
/**
* @param[in] iChannels Number of channels
* @param[in] dSamplingRate Sampling rate
* @param[in] iBufferSize Size of audio streaming buffer
* @param[in] iRingBufferCapacity Internal ring buffer
*
* The ring buffer capacity should be roughly 6-10 buffer sizes long for short audio streaming buffers,
* and can go down to one block in case of higher audio buffer sizes.
*
* The streaming parameters have to match with the server settings (yes also buffer size, that of the audio streaming context)
*
* @note Accept for more memory usage, oversizing the buffer does not require more CPU.
*/
CITANetAudioStream
(
const
int
iChannels
,
const
double
dSamplingRate
,
const
int
iBufferSize
,
const
int
iRingBufferCapacity
=
2048
);
virtual
~
CITANetAudioStream
();
//! Network streaming status of client
...
...
@@ -68,16 +81,20 @@ public:
STOPPED
,
//!< Client not connected to a server and streaming stopped, i.e. not receiving samples by choice
CONNECTED
,
//!< Client is connected to a sample server (and potentially receives samples)
STREAMING
,
//!<
BUFFER_UNDERRUN
,
BUFFER_OVERRUN
,
BUFFER_UNDERRUN
,
//!< Client internal audio buffer ran out of samples
BUFFER_OVERRUN
,
//!< Client internal audio ring buffer is full
};
//! Connect a streaming server
/**
* @sAddress[in] Server address IP
, i.e. 127.0.0.1
* @sAddress[in] Server address IP
(127.0.0.1, localhost, etc.)
* @iPort[in] Server socket port, defaults to 12480
* @return True, if connection could be established and streaming parameters match
*/
bool
Connect
(
const
std
::
string
&
sAddress
,
int
iPort
=
12480
);
bool
Connect
(
const
std
::
string
&
sAddress
,
const
int
iPort
=
12480
,
const
bool
bUseUDP
=
false
);
//! Disconnct safely from server
void
Disconnect
();
//! Returns the connection status
/**
...
...
@@ -85,43 +102,47 @@ public:
*/
bool
GetIsConnected
()
const
;
//!
Set allowed latency (s
)
//!
Returns the minimal latency possible (single block
)
/**
* Sets the latency that will be used for reading and writing from ring buffer.
* New samples will be requested and send if the latency / ring buffer samples
* is lower than the target latency.
*/
void
SetAllowedLatencySeconds
(
float
fLatencySeconds
);
void
SetAllowedLatencySamples
(
int
iLatencySamples
);
float
GetAllowedLatencySeconds
()
const
;
int
GetAllowedLatencySamples
()
const
;
//! Sets the minimal latency possible
/**
* Real-time network audio is considered to process at lowest latency possible.
* However, this implementation requires at least one block. Hence latency is
* depending on sampling rate and block length.
*
* @sa GetMinimumLatencySamples()
* @sa GetMinimumLatencySamples()
* @return Minimum latency in seconds
*/
float
GetMinimumLatencySeconds
()
const
;
//! Returns the maximum latency possible (entire ring buffer used)
/**
* @return Maximum latency in seconds
*/
float
GetMaximumLatencySeconds
()
const
;
//! Returns the minimum latency possible (single block)
/**
* @return Minimum latency in samples
*/
int
GetMinimumLatencySamples
()
const
;
//! Returns the maximum latency possible (entire ring buffer used)
/**
* @return Maximum latency in samples
*/
int
GetMaximumLatencySamples
()
const
;
//! Sets the latency for real-time processing
//! Returns the NetAudio streaming logger base name
std
::
string
GetNetAudioStreamLoggerBaseName
()
const
;
//! Sets the NetAudio streaming logger base name
/**
* Real-time network audio is considered to process at lowest latency possible.
* However, this implementation requires at least one block. Hence latency is
* depending on sampling rate and block length. This method basically
* sets the minimum allowed latency to this value.
*
* @sa GetMinimumLatencySeconds()
* @sa SetAllowedLatencySeconds()
* If debugging is enabled, all debugging files will be named
* with this suffix.
* @param[in] sBaseName Base name string
*
*/
void
SetLatencyForRealtime
();
void
SetNetAudioStreamingLoggerBaseName
(
const
std
::
string
&
sBaseName
);
//! Enabled/disables export of loggers
void
SetDebuggingEnabled
(
bool
bEnabled
);
//! Logging export flag getter
bool
GetIsDebuggingEnabled
()
const
;
//! Returns (static) size of ring buffer
/**
...
...
@@ -167,6 +188,7 @@ public:
*/
void
IncrementBlockPointer
();
protected:
//! This method is called by the networkg client and pushes samples into the ring buffer
/**
...
...
@@ -180,7 +202,7 @@ protected:
*
* @note This method is not called out of the audio streaming context but out of the network context.
*/
int
Transmit
(
const
ITASampleFrame
&
sfNewSamples
,
int
iNumSamples
);
int
Transmit
(
const
ITASampleFrame
&
sfNewSamples
,
const
int
iNumSamples
);
//! Returns samples that can be read from ring buffer
/**
...
...
@@ -194,6 +216,9 @@ protected:
*/
int
GetRingBufferFreeSamples
()
const
;
//! Returns a string for the streaming status identifier
static
std
::
string
GetStreamingStatusString
(
const
int
iStreamingStatus
);
private:
CITANetAudioStreamingClient
*
m_pNetAudioStreamingClient
;
//!< Audio streaming network client
...
...
@@ -204,16 +229,17 @@ private:
int
m_iWriteCursor
;
//!< Cursor where samples will be fed into ring buffer from net audio producer (always ahead)
bool
m_bRingBufferFull
;
//!< Indicator if ring buffer is full (and read cursor equals write cursor)
ITASampleFrame
m_sfRingBuffer
;
//!< Ring buffer
int
m_iTargetSampleLatency
;
//!< Maximum allowed samples / target sample latency
int
m_iStreamingStatus
;
//!< Current streaming status
double
m_dLastStreamingTimeCode
;
ITABufferedDataLoggerImplAudio
*
m_pAudioLogger
;
//!< Logging for the audio stream
ITABufferedDataLoggerImplStream
*
m_pStreamLogger
;
//!< Logging for the audio stream
ITABufferedDataLoggerImplNet
*
m_pNetLogger
;
//!< Logging for the network stream
int
iAudioStreamingBlockID
;
//!< Audio streaming block id
int
iNetStreamingBlockID
;
//!< Network streaming block id
ITABufferedDataLoggerImplStream
*
m_pAudioStreamLogger
;
//!< Logging for the audio stream
ITABufferedDataLoggerImplNet
*
m_pNetworkStreamLogger
;
//!< Logging for the network stream
std
::
string
m_sNetAudioStreamLoggerBaseName
;
bool
m_bDebuggingEnabled
;
int
m_iAudioStreamingBlockID
;
//!< Audio streaming block id
int
m_iNetStreamingBlockID
;
//!< Network streaming block id
friend
class
CITANetAudioStreamingClient
;
};
...
...
include/ITANetAudioStreamingServer.h
View file @
b3f9d3d1
...
...
@@ -21,60 +21,72 @@
#include <ITADataSourcesDefinitions.h>
#include <ITANetAudioProtocol.h>
#include <ITASampleFrame.h>
#include <ITAStopWatch.h>
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <ITANetAudioProtocol.h>
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
#include <ITASampleFrame.h>
#include <iostream>
class
ITADatasource
;
class
CITANetAudioMessage
;
class
CITANetAudioProtocol
;
class
CITANetAudioServer
;
class
CITANetAudioMessage
;
class
VistaTCPSocket
;
class
CITABufferedDataLoggerImplServer
;
class
VistaConnectionIP
;
//! Network audio sample server (for connecting a net audio stream)
//! Network audio streaming server (for connecting a net audio stream) with an ITADataSource connection
/**
* Audio sample transmitter for a networked signal source that can connect via TCP/IP.
*
* \
sa CITANetAudioStream
* \
note not thread-safe
*/
* Audio sample transmitter for a networked signal source that can connect via TCP/IP.
*
* @
sa CITANetAudioStream
* @
note not thread-safe
*/
class
ITA_DATA_SOURCES_API
CITANetAudioStreamingServer
:
public
VistaThreadLoop
{
public:
enum
UpdateStrategy
{
AUTO
=
1
,
//!< Automatic update rate based on sample rate and block length of client (default)
ADAPTIVE
,
//!< Adaptive update rate, adjusts for drifting clocks
CONSTANT
,
//!< Set a user-defined update rate (may cause forced pausing of sample feeding or dropouts on client side)
};
CITANetAudioStreamingServer
();
virtual
~
CITANetAudioStreamingServer
()
{}
;
~
CITANetAudioStreamingServer
()
;
bool
Start
(
const
std
::
string
&
sAddress
,
int
iPort
);
//! Start to listen on a socket (blocking)
bool
Start
(
const
std
::
string
&
sAddress
,
const
int
iPort
,
const
double
dTimeIntervalCientSendStatus
,
const
bool
bUseUDP
=
false
);
bool
IsClientConnected
()
const
;
std
::
string
GetNetworkAddress
()
const
;
int
GetNetworkPort
()
const
;
bool
LoopBody
();
void
Stop
();
void
SetInputStream
(
ITADatasource
*
pInStream
);
int
GetNetStreamBlocklength
()
const
;
int
GetNetStreamNumberOfChannels
()
const
;
double
GetNetStreamSampleRate
()
const
;
int
GetNetStreamNumberOfChannels
(
)
const
;
double
GetNetStreamSampleRate
(
)
const
;
double
GetEstimatedCorrFactor
(
)
const
;
void
SetEstimatedCorrFactor
(
double
dcorrFactor
);
//! Enabled/disables export of loggers
void
SetDebuggingEnabled
(
bool
bEnabled
);
//! Logging export flag getter
bool
GetIsDebuggingEnabled
()
const
;
int
GetSendingBlockLength
()
const
;
void
SetSendingBlockLength
(
const
int
iSendingBlockLength
);
void
SetAutomaticUpdateRate
();
void
SetTargetLatencySamples
(
const
int
iTargetLatency
);
int
GetTargetLatencySamples
()
const
;
void
SetServerLogBaseName
(
const
std
::
string
&
sBaseName
);
std
::
string
GetServerLogBaseName
()
const
;
bool
LoopBody
();
protected:
ITADatasource
*
GetInputStream
()
const
;
...
...
@@ -85,12 +97,25 @@ private:
ITADatasource
*
m_pInputStream
;
VistaConnectionIP
*
m_pConnection
;
CITANetAudioProtocol
::
StreamingParameters
m_oServerParams
;
CITANetAudioMessage
*
m_pIncomingMessage
;
CITANetAudioMessage
*
m_pOutgoingMessage
;
CITANetAudioMessage
*
m_pMessage
;
CITABufferedDataLoggerImplServer
*
m_pServerLogger
;
std
::
string
m_sServerLogBaseName
;
ITAStopWatch
m_swTryReadBlockStats
,
m_swTryReadAccessStats
;
bool
m_bDebuggingEnabled
;
int
m_iServerBlockId
;
double
m_dLastTimeStamp
;
double
m_dEstimatedCorrFactor
;
int
m_iTargetLatencySamples
;
int
m_iEstimatedClientRingBufferFreeSamples
;
int
m_iClientRingBufferSize
;
int
m_iSendingBlockLength
;
int
m_iMaxSendBlocks
;
int
m_iUpdateStrategy
;
int
m_iClientRingBufferFreeSamples
;
double
m_dStreamTimeStart
;
//!< Stream time start
long
unsigned
int
m_nStreamSampleCounts
;
//!< Samples that has been streamed
friend
class
CITANetAudioServer
;
};
...
...
include/ITAStreamInfo.h
View file @
b3f9d3d1
// $Id: $
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef
__ITA_STREAM_INFO_H__
#define
__ITA_STREAM_INFO_H__
#ifndef
INCLUDE_WATCHER_ITA_STREAM_INFO
#define
INCLUDE_WATCHER_ITA_STREAM_INFO
#include <ITATypes.h>
// Diese Datenklasse beschreibt den Zustand eines Audiostreams
class
ITAStreamInfo
{
//! Time code information for audio streams
class
ITAStreamInfo
{
public:
// Anzahl der abgespielten Samples seit Beginn des Streamings
uint64_t
nSamples
;
uint64_t
nSamples
;
//!< Number of samples processed
double
dStreamTimeCode
;
//!< Stream time code (starts with zero)
double
dSysTimeCode
;
//!< System time stamp code (begings with current time stamp of system)
// TODO: Beschreiben
double
dTimecode
;
inline
ITAStreamInfo
()
:
nSamples
(
0
)
,
dStreamTimeCode
(
0.0
f
)
,
dSysTimeCode
(
0.0
f
)
{};
//! Standard-Konstruktor (setzt alle Werte 0)
ITAStreamInfo
()
:
nSamples
(
0
),
dTimecode
(
0
)
{}
//! Destruktor
virtual
~
ITAStreamInfo
()
{};
inline
virtual
~
ITAStreamInfo
()
{};
};
#endif //
__ITA_STREAM_INFO_H__
#endif //
INCLUDE_WATCHER_ITA_STREAM_INFO
include/ITAStreamPatchBay.h
View file @
b3f9d3d1
...
...
@@ -220,7 +220,7 @@ private:
ITADatasource
*
pDatasource
;
//!< Datasource assigned to the input
std
::
vector
<
const
float
*
>
vpfInputData
;
//!< Pointers to the next stream blocks
inline
InputDesc
(
const
int
iChannels
,
const
int
iBlockLength
)
inline
InputDesc
(
const
int
iChannels
,
const
int
)
:
vpfInputData
(
iChannels
,
nullptr
)
,
iChannels
(
iChannels
)
,
fCurrentGain
(
1.0
f
)
...
...
src/ITAAsioInterface.cpp
View file @
b3f9d3d1
#
include
<
ITAAsioInterface
.
h
>
#include <ITAAtomicPrimitives.h>
#include <ITADatasource.h>
#include <ITAException.h>
#include <ITAStreamInfo.h>
#include <ITADatasource.h>
#include <ITADatasourceRealization.h>
#include <ITAAtomicPrimitives.h>
#include <ITAClock.h>
#include <ITADatasource.h>
#include <ITAException.h>
#include <ITAStopWatch.h>
#include <ITAStringUtils.h>
#include <host/asiodrivers.h>
#include <windows.h>
...
...
@@ -17,17 +21,14 @@
// Puffer-Vielfachheit (Doppelpuffer, Dreifachpuffer, etc.)
const
unsigned
int
ASIOSOURCE_BUFFER_MULTIPLICITY
=
16
;
class
ASIOSource
:
public
ITADatasourceRealization
{
class
ASIOSource
:
public
ITADatasourceRealization
{
public:
ASIOSource
(
unsigned
int
uiChannels
,
double
dSamplerate
,
unsigned
int
uiBlocklength
)
:
ITADatasourceRealization
(
uiChannels
,
dSamplerate
,
uiBlocklength
,
ASIOSOURCE_BUFFER_MULTIPLICITY
)
{}
friend
ASIOTime
*
bufferSwitchTimeInfo
(
ASIOTime
*
timeInfo
,
long
index
,
ASIOBool
processNow
);
inline
ASIOSource
(
unsigned
int
uiChannels
,
double
dSamplerate
,
unsigned
int
uiBlocklength
)
:
ITADatasourceRealization
(
uiChannels
,
dSamplerate
,
uiBlocklength
,
ASIOSOURCE_BUFFER_MULTIPLICITY
)
{};
friend
ASIOTime
*
bufferSwitchTimeInfo
(
ASIOTime
*
timeInfo
,
long
index
,
ASIOBool
processNow
);
};
// WICHTIG: Dieses Makro legt fest, wieviele Blöcke Eingangsdaten nach
...
...
@@ -43,13 +44,14 @@ public:
// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
#if NATIVE_INT64
#define ASIO64toDouble(a) (a)
#define ASIO64toDouble(a) (a)
#else
const
double
twoRaisedTo32
=
4294967296.
;
#define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
const
double
twoRaisedTo32
=
4294967296.
;
#define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
#endif
typedef
struct
DriverInfo
{
typedef
struct
DriverInfo
{
// Zugehörige ASIO-Treiberinfo (Achtung: Datentyp "ASIODriverInfo")
ASIODriverInfo
driverInfo
;
...
...
@@ -76,11 +78,11 @@ typedef struct DriverInfo {
// Anzahl der Ein-/Ausgabepuffer
long
inputBuffers
;
// becomes number of actual created input buffers
long
outputBuffers
;
// becomes number of actual created output buffers
// ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels]; // buffer info's
// ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels]; // buffer info's
std
::
vector
<
ASIOBufferInfo
>
bufferInfos
;
// buffer info's
// ASIOGetChannelInfo()
// ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
// ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
std
::
vector
<
ASIOChannelInfo
>
channelInfos
;
// channel info's
// The above two arrays share the same indexing, as the data in them are linked together
...
...
@@ -99,42 +101,45 @@ typedef struct DriverInfo {
}
DriverInfo
;
// Statusflags
const
long
LIBRAW
=
-
1
;
// Bibliothek wurde noch nicht initialisiert
const
long
LOADED
=
0
;
// Bibliothek wurde initialisiert
const
long
LIBRAW
=
-
1
;
// Bibliothek wurde noch nicht initialisiert
const
long
LOADED
=
0
;
// Bibliothek wurde initialisiert
const
long
INITIALIZED
=
1
;
// ASIO-Treiber wurde initialisiert
const
long
PREPARED
=
2
;
// ASIO-Streaming wurde vorbereitet
const
long
RUNNING
=
3
;
// ASIO-Streaming läuft
const
long
PREPARED
=
2
;
// ASIO-Streaming wurde vorbereitet
const
long
RUNNING
=
3
;
// ASIO-Streaming läuft
HANDLE
hStopEvent
=
0
;
// Event, welches "Bereit zum Stoppen" signalisiert
CRITICAL_SECTION
csInternal
;
// Kritischer Bereich: Interne Synchronisation
CRITICAL_SECTION
csExternal
;
// Kritischer Bereich: Externe Synchronisation
long
lState
=
LIBRAW
;
// Aktueller Zustand
bool
bPreInit
=
false
;
// Treiber-Komponente initialisiert und aufgezählt?
long
lState
=
LIBRAW
;
// Aktueller Zustand
bool
bPreInit
=
false
;
// Treiber-Komponente initialisiert und aufgezählt?
int
iZeroBlocks
;
// Anzahl der noch zu spielenden Nullblöcke (nach Stop)
long
lNumDrivers
;
// Anzahl der installierten Treiber
char
**
asioDriverNames
=
NULL
;
// Zwischerspeicher für die Treibernamen
DriverInfo
asioDriverInfo
;
// Eigene Treiberinfos
float
fOutputGain
=
1.0
;
// Verstärkungsfaktor für Wiedergabe
float
fOutputGain
=
1.0
;
// Verstärkungsfaktor für Wiedergabe
long
volatile
lAsioBufferIndex
;
ASIOBool
abProcessNow
;
float
*
pfSilence
=
0
;
float
*
pfInputBuffer
=
0
;
float
*
pfInputDummyBuffer
=
0
;
// Puffer für die zu verwerfenden ersten zwei Blöcke
float
*
pfSilence
=
0
;
float
*
pfInputBuffer
=
0
;
float
*
pfInputDummyBuffer
=
0
;
// Puffer für die zu verwerfenden ersten zwei Blöcke
ASIOSource
*
pasInputDatasource
=
0
;
// Eingabedatenquelle
ITADatasource
*
pidsOutputDatasource
=
0
;
// Ausgabedatenquelle
ASIOSource
*
pasInputDatasource
=
0
;
// Eingabedatenquelle
ITADatasource
*
pidsOutputDatasource
=
0
;
// Ausgabedatenquelle
ITAStreamInfo
siStreamInfo
;
// Zustandsinformationen des Streams
double
g_dStreamStartTimeStamp
=
ITAClock
::
getDefaultClock
()
->
getTime
();
//!< Time stamp at beginning of streaming
unsigned
long
ulOutput
Counter
=
0
;
unsigned
long
ulInputCounter
=
0
;
unsigned
long
ulInputPresentCounter
=
0
;
int
iInputBufferNrOffset
=
0
;
unsigned
long
ulOutput
BlockCounter
=
0
;
unsigned
long
ulInputCounter
=
0
;
unsigned
long
ulInputPresentCounter
=
0
;
int
iInputBufferNrOffset
=
0
;
long
lBuffersize
=
0
;
// Ausgewählte Puffergröße
long
lBuffersize
=
0
;
// Ausgewählte Puffergröße
ITAAtomicInt
iBufferswitchEntrances
(
0
);
ITAAtomicInt
iBufferswitchEntrances
(
0
);
ITAStopWatch
g_swStreamOutputProcessing
;
// -= Externe Referenzen =-
extern
AsioDrivers
*
asioDrivers
;
...
...
@@ -145,113 +150,113 @@ extern AsioDrivers *asioDrivers;
| ASIO-Callbacks |
| |
+------------------+
*/
*/
ASIOCallbacks
asioCallbacks
;
ASIOTime
*
bufferSwitchTimeInfo
(
ASIOTime
*
timeInfo
,
long
index
,
ASIOBool
processNow
)
{
ASIOTime
*
bufferSwitchTimeInfo
(
ASIOTime
*
timeInfo
,
long
index
,
ASIOBool
processNow
)
{
// The actual processing callback.
/* Beware that this is normally in a seperate thread,
hence be sure that you take care about thread synchronization.
hence be sure that you take care about thread synchronization.
This is omitted here for simplicity. */
if
(
++
iBufferswitchEntrances
>
1
)
if
(
++
iBufferswitchEntrances
>
1
)
std
::
cerr
<<
"Problem: ASIO bufferswitch callback reentrance!
\n
"
<<
std
::
endl
;
// Internen Mutex in Besitz bringen
EnterCriticalSection
(
&
csInternal
);
EnterCriticalSection
(
&
csInternal
);
// Store the timeInfo for later use
asioDriverInfo
.
tInfo
=
*
timeInfo
;
lAsioBufferIndex
=
index
;
abProcessNow
=
processNow
;
long
lCounter
=
0
;
static
long
processedSamples
=
0
;
// Get the time stamp of the buffer, not necessary if no
// synchronization to other media is required
if
(
timeInfo
->
timeInfo
.
flags
&
kSystemTimeValid
)
asioDriverInfo
.
nanoSeconds
=
ASIO64toDouble
(
timeInfo
->
timeInfo
.
systemTime
);
if
(
timeInfo
->
timeInfo
.
flags
&
kSystemTimeValid
)
asioDriverInfo
.
nanoSeconds
=
ASIO64toDouble
(
timeInfo
->
timeInfo
.
systemTime
);
else
asioDriverInfo
.
nanoSeconds
=
0
;
if
(
timeInfo
->
timeInfo
.
flags
&
kSamplePositionValid
)
asioDriverInfo
.
samples
=
ASIO64toDouble
(
timeInfo
->
timeInfo
.
samplePosition
);
if
(
timeInfo
->
timeInfo
.
flags
&
kSamplePositionValid
)
asioDriverInfo
.
samples
=
ASIO64toDouble
(
timeInfo
->
timeInfo
.
samplePosition
);
else
asioDriverInfo
.
samples
=
0
;
if
(
timeInfo
->
timeCode
.
flags
&
kTcValid
)
asioDriverInfo
.
tcSamples
=
ASIO64toDouble
(
timeInfo
->
timeCode
.
timeCodeSamples
);
if
(
timeInfo
->
timeCode
.
flags
&
kTcValid
)
asioDriverInfo
.
tcSamples
=
ASIO64toDouble
(
timeInfo
->
timeCode
.
timeCodeSamples
);
else
asioDriverInfo
.
tcSamples
=
0
;
// Get the system reference time
asioDriverInfo
.
sysRefTime
=
timeGetTime
();
// link winmm.lib
/*
DEBUG_PRINTF("[ITAsioInterface] nanoSeconds = %0.1f, samples = %0.1f, tcSamples = %0.1f, sysRefTime = %0.1f\n",
asioDriverInfo.nanoSeconds, asioDriverInfo.samples, asioDriverInfo.tcSamples, asioDriverInfo.sysRefTime);
*/
/*
DEBUG_PRINTF("[ITAsioInterface] nanoSeconds = %0.1f, samples = %0.1f, tcSamples = %0.1f, sysRefTime = %0.1f\n",
asioDriverInfo.nanoSeconds, asioDriverInfo.samples, asioDriverInfo.tcSamples, asioDriverInfo.sysRefTime);
*/
// [Bugfix fwe]: Schwerer Bug! long buffSize = asioDriverInfo.preferredSize;
int
j
;
int
iCount
=
0
;
float
fScaling
=
0
;
int
iChannelNumber
=
0
;
// -= Eingabedaten lesen =-
/* Hinweis: Eingabedaten werden nur gelesen, falls ASIO-Stop noch
nicht aufgerufen wurde, d.h. iZeroBlocks == -1 ist. */
if
(
iZeroBlocks
==
-
1
)
/* Hinweis: Eingabedaten werden nur gelesen, falls ASIO-Stop noch
nicht aufgerufen wurde, d.h. iZeroBlocks == -1 ist. */
if
(
iZeroBlocks
==
-
1
)
{
bool
bInputDataPresent
=
(
ulInputPresentCounter
>=
NUM_INPUT_BLOCKS_TO_DISCARD
)
&&
(
pasInputDatasource
!=
0
);
bool
bInputDataPresent
=
(
ulInputPresentCounter
>=
NUM_INPUT_BLOCKS_TO_DISCARD
)
&&
(
pasInputDatasource
!=
0
);
// Input-Kanaele lesen
for
(
int
i
=
0
;
i
<
asioDriverInfo
.
inputBuffers
+
asioDriverInfo
.
outputBuffers
;
i
++
)
{
if
(
asioDriverInfo
.
bufferInfos
[
i
].
isInput
==
TRUE
)
{
if
(
i
>=
asioDriverInfo
.
inputBuffers
)
MessageBoxA
(
0
,
"Error"
,
"Input Buffer Overflow"
,
MB_OK
|
MB_SYSTEMMODAL
|
MB_APPLMODAL
);
for
(
int
i
=
0
;
i
<
asioDriverInfo
.
inputBuffers
+
asioDriverInfo
.
outputBuffers
;
i
++
)
{
if
(
asioDriverInfo
.
bufferInfos
[
i
].
isInput
==
TRUE
)
{
if
(
i
>=
asioDriverInfo
.
inputBuffers
)
MessageBoxA
(
0
,
"Error"
,
"Input Buffer Overflow"
,
MB_OK
|
MB_SYSTEMMODAL
|
MB_APPLMODAL
);
else
iChannelNumber
=
i
;
if
(
!
bInputDataPresent
)
{
if
(
!
bInputDataPresent
)
{
// Noch keine Eingabesamples: Stille bereistellen
float
*
pfBuffer
=
pasInputDatasource
->
GetWritePointer
(
iChannelNumber
);
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
pfBuffer
[
j
]
=
0
;
}
else
{
float
*
pfBuffer
=
pasInputDatasource
->
GetWritePointer
(
iChannelNumber
);
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
pfBuffer
[
j
]
=
0
;
}
else
{
// Eingabesamples verfügbar. Samples konvertieren.
pfInputBuffer
=
pasInputDatasource
->
GetWritePointer
(
iChannelNumber
);
pfInputBuffer
=
pasInputDatasource
->
GetWritePointer
(
iChannelNumber
);
switch
(
asioDriverInfo
.
channelInfos
[
i
].
type
)
{
case
ASIOSTInt16LSB
:
switch
(
asioDriverInfo
.
channelInfos
[
i
].
type
)
{
case
ASIOSTInt16LSB
:
__int16
*
psAsioBufPtr
;
psAsioBufPtr
=
(
__int16
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
psAsioBufPtr
=
(
__int16
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
// Konvertierung Int16 nach Float
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
pfInputBuffer
[
j
]
=
((
float
)
psAsioBufPtr
[
j
]
)
/
32767.0
F
;
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
pfInputBuffer
[
j
]
=
(
(
float
)
psAsioBufPtr
[
j
]
)
/
32767.0
F
;
break
;
case
ASIOSTInt24LSB
:
// used for 20 bits as well
char
*
pcAsioBufPtr
;
pcAsioBufPtr
=
(
char
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
pcAsioBufPtr
=
(
char
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
__int32
i32Temp
;
i32Temp
=
0
;
// Konvertierung 20/24-Bit Integer nach Float
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
{
memcpy
(
&
i32Temp
,
pcAsioBufPtr
,
3
);
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
{
memcpy
(
&
i32Temp
,
pcAsioBufPtr
,
3
);
pcAsioBufPtr
+=
3
;
pfInputBuffer
[
j
]
=
((
float
)
i32Temp
)
/
8388607.0
F
;
}
pfInputBuffer
[
j
]
=
(
(
float
)
i32Temp
)
/
8388607.0
F
;
}
break
;
case
ASIOSTInt32LSB
:
__int32
*
piAsioBufPtr
;
piAsioBufPtr
=
(
__int32
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
piAsioBufPtr
=
(
__int32
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
/*
* Bugfix [fwe 2008-09-24]:
...
...
@@ -263,16 +268,16 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
* (Entspricht wieder den 24 Bit nominell). Demnach ist
* der Skalierungsfaktor für Vollaussteuerung nicht
* 2^31-1 = 2147483647, sondern (2^23-1)*2^8 = 2147483392
*
*
* Klärung mit RME Audio steht noch aus...
*/
// Konvertierung 32-Bit Integer nach Float
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
// Standard-Implementierung:
//pfInputBuffer[j] = ((float) piAsioBufPtr[j]) / 2147483647.0F;
// RME-Hammerfall Safe Implementierung
pfInputBuffer
[
j
]
=
((
float
)
piAsioBufPtr
[
j
])
/
2147483392.0
F
;
pfInputBuffer
[
j
]
=
(
(
float
)
piAsioBufPtr
[
j
]
)
/
2147483392.0
F
;
break
;
}
...
...
@@ -280,20 +285,25 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
}
}
if
(
pasInputDatasource
)
pasInputDatasource
->
IncrementWritePointer
();
if
(
pasInputDatasource
)
pasInputDatasource
->
IncrementWritePointer
();
}
// -= Ausgabedaten schreiben =-
/* Hinweis: Falls iZeroBlocks != -1 ist wurde ASIOStop bereits ausgelöst und
jetzt müssen Nullblöcke abgespielt werden.
jetzt müssen Nullblöcke abgespielt werden.
iZeroBlocks muß heruntergezählt werden. */
// Output-Kanaele schreiben
for
(
int
i
=
0
;
i
<
asioDriverInfo
.
inputBuffers
+
asioDriverInfo
.
outputBuffers
;
i
++
)
{
if
(
asioDriverInfo
.
bufferInfos
[
i
].
isInput
==
FALSE
)
{
if
(
i
-
asioDriverInfo
.
inputBuffers
>=
asioDriverInfo
.
outputBuffers
)
MessageBoxA
(
0
,
"Error"
,
"Output Buffer Overflow"
,
MB_OK
|
MB_SYSTEMMODAL
|
MB_APPLMODAL
);
// Provide ouput data
g_swStreamOutputProcessing
.
start
();
for
(
int
i
=
0
;
i
<
asioDriverInfo
.
inputBuffers
+
asioDriverInfo
.
outputBuffers
;
i
++
)
{
if
(
asioDriverInfo
.
bufferInfos
[
i
].
isInput
==
FALSE
)
{
if
(
i
-
asioDriverInfo
.
inputBuffers
>=
asioDriverInfo
.
outputBuffers
)
MessageBoxA
(
0
,
"Error"
,
"Output Buffer Overflow"
,
MB_OK
|
MB_SYSTEMMODAL
|
MB_APPLMODAL
);
else
iChannelNumber
=
i
-
asioDriverInfo
.
inputBuffers
;
...
...
@@ -302,49 +312,52 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
// TODO: Streaminfo zusammenstellen? TimeCode aus ASIO rein?
// Gibts eine Ausgabedatenquelle?
if
(
pidsOutputDatasource
&&
(
iZeroBlocks
==
-
1
))
{
if
(
pidsOutputDatasource
&&
(
iZeroBlocks
==
-
1
)
)
{
// Dann Datenzeiger der Quelle abrufen
// Wichtig: false ist enorm wichtig, damit nicht auf Daten gewartet wird!
pfOutputData
=
pidsOutputDatasource
->
GetBlockPointer
(
(
unsigned
int
)
iChannelNumber
,
&
siStreamInfo
);
pfOutputData
=
pidsOutputDatasource
->
GetBlockPointer
(
(
unsigned
int
)
iChannelNumber
,
&
siStreamInfo
);
// Falls die Quelle keine Daten hat, Stille verwenden
if
(
!
pfOutputData
)
pfOutputData
=
pfSilence
;
if
(
!
pfOutputData
)
pfOutputData
=
pfSilence
;
}
switch
(
asioDriverInfo
.
channelInfos
[
i
].
type
)
switch
(
asioDriverInfo
.
channelInfos
[
i
].
type
)
{
case
ASIOSTInt16LSB
:
#if DEBUG_OUT
std
::
cout
<<
"ASIOSTInt16LSB nicht unterstuetzt "
;
#endif
#if DEBUG_OUT
std
::
cout
<<
"ASIOSTInt16LSB nicht unterstuetzt "
;
#endif
__int16
*
psAsioBufPtr
;
psAsioBufPtr
=
(
__int16
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
fScaling
=
32767.0
F
*
fOutputGain
;
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
psAsioBufPtr
[
j
]
=
(
__int16
)
(
pfOutputData
[
j
]
*
fScaling
);
psAsioBufPtr
=
(
__int16
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
fScaling
=
32767.0
F
*
fOutputGain
;
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
psAsioBufPtr
[
j
]
=
(
__int16
)
(
pfOutputData
[
j
]
*
fScaling
);
break
;
case
ASIOSTInt24LSB
:
// used for 20 bits as well
#if DEBUG_OUT
std
::
cout
<<
"ASIOSTInt24LSB nicht unterstuetzt "
;
#endif
#if DEBUG_OUT
std
::
cout
<<
"ASIOSTInt24LSB nicht unterstuetzt "
;
#endif
char
*
pcAsioBufPtr
;
pcAsioBufPtr
=
(
char
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
pcAsioBufPtr
=
(
char
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
__int32
i32Temp
;
char
*
pcSourcePointer
;
fScaling
=
8388607.0
F
*
fOutputGain
;
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
{
i32Temp
=
(
__int32
)
(
pfOutputData
[
j
]
*
fScaling
);
pcSourcePointer
=
(
char
*
)
&
i32Temp
;
memcpy
(
pcAsioBufPtr
,
pcSourcePointer
,
3
);
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
{
i32Temp
=
(
__int32
)
(
pfOutputData
[
j
]
*
fScaling
);
pcSourcePointer
=
(
char
*
)
&
i32Temp
;
memcpy
(
pcAsioBufPtr
,
pcSourcePointer
,
3
);
pcAsioBufPtr
+=
3
;
}
}
break
;
case
ASIOSTInt32LSB
:
#if DEBUG_OUT
std
::
cout
<<
"ASIOSTInt32LSB nicht unterstuetzt"
;
#endif
#if DEBUG_OUT
std
::
cout
<<
"ASIOSTInt32LSB nicht unterstuetzt"
;
#endif
/*
* Bugfix [fwe 2008-09-24]:
...
...
@@ -356,20 +369,20 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
* (Entspricht wieder den 24 Bit nominell). Demnach ist
* der Skalierungsfaktor für Vollaussteuerung nicht
* 2^31-1 = 2147483647, sondern (2^23-1)*2^8 = 2147483392
*
*
* Klärung mit RME Audio steht noch aus...
*/
__int32
*
piAsioBufPtr
;
piAsioBufPtr
=
(
__int32
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
piAsioBufPtr
=
(
__int32
*
)
asioDriverInfo
.
bufferInfos
[
i
].
buffers
[
lAsioBufferIndex
];
//fScaling = 2147483647.0F * fOutputGain;
fScaling
=
2147483392.0
F
*
fOutputGain
;
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
piAsioBufPtr
[
j
]
=
(
__int32
)
(
pfOutputData
[
j
]
*
fScaling
);
break
;
for
(
j
=
0
;
j
<
lBuffersize
;
j
++
)
piAsioBufPtr
[
j
]
=
(
__int32
)
(
pfOutputData
[
j
]
*
fScaling
);
break
;
// Alles weitere wird noch nicht unterstützt!!
// Int
// Alles weitere wird noch nicht unterstützt!!
// Int
case
ASIOSTInt32LSB16
:
// 32 bit data with 18 bit alignment
std
::
cout
<<
"ASIOSTInt32LSB16 nicht unterstuetzt "
;
break
;
...
...
@@ -392,8 +405,8 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
std
::
cout
<<
"ASIOSTInt32MSB nicht unterstuetzt "
;
break
;
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can more easily used with these
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can more easily used with these
case
ASIOSTInt32MSB16
:
// 32 bit data with 18 bit alignment
std
::
cout
<<
"ASIOSTInt32MSB16 nicht unterstuetzt "
;
break
;
...
...
@@ -407,7 +420,7 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
std
::
cout
<<
"ASIOSTInt32MSB24 nicht unterstuetzt "
;
break
;
// Float
// Float
case
ASIOSTFloat32LSB
:
// IEEE 754 32 bit float, as found on Intel x86 architecture
std
::
cout
<<
"ASIOSTFloat32LSB nicht unterstuetzt "
;
break
;
...
...
@@ -422,34 +435,40 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
std
::
cout
<<
"ASIOSTFloat64MSB nicht unterstuetzt"
;
break
;
default:
std
::
cout
<<
"- "
;
std
::
cout
<<
"- "
;
}
}
}
ulOutputCounter
++
;
const
double
dOutputProcessingTime
=
g_swStreamOutputProcessing
.
stop
();
const
double
dAvailabelProcessingTime
=
double
(
lBuffersize
)
/
double
(
asioDriverInfo
.
sampleRate
);
if
(
dOutputProcessingTime
>
dAvailabelProcessingTime
)
std
::
cerr
<<
"[ ITAAsioInterface ] Output stream panic, processing time exceeded ( took "
<<
timeToString
(
dOutputProcessingTime
)
<<
" but got only "
<<
timeToString
(
dAvailabelProcessingTime
)
<<
" )"
<<
std
::
endl
;
if
(
ulInputPresentCounter
<=
1
)
ulOutputBlockCounter
++
;
if
(
ulInputPresentCounter
<=
1
)
ulInputPresentCounter
++
;
else
ulInputCounter
++
;
processedSamples
+=
lBuffersize
;
// Zwischenlüsung: Streaminfo einfach inkrementieren. Keinen Timcode.
siStreamInfo
.
nSamples
+=
lBuffersize
;
siStreamInfo
.
dTimecode
=
(
double
)
(
siStreamInfo
.
nSamples
)
/
(
double
)
asioDriverInfo
.
sampleRate
;
//siStreamInfo.dStreamTimeCode = (double) (siStreamInfo.nSamples) / (double) asioDriverInfo.sampleRate;
siStreamInfo
.
dStreamTimeCode
=
ITAClock
::
getDefaultClock
()
->
getTime
()
-
g_dStreamStartTimeStamp
;
siStreamInfo
.
dSysTimeCode
=
ITAClock
::
getDefaultClock
()
->
getTime
();
// Gibts eine Ausgabedatenquelle? Dann Blockzeiger weitersetzen
if
(
pidsOutputDatasource
&&
(
iZeroBlocks
==
-
1
)
)
pidsOutputDatasource
->
IncrementBlockPointer
();
if
(
pidsOutputDatasource
&&
(
iZeroBlocks
==
-
1
)
)
pidsOutputDatasource
->
IncrementBlockPointer
();
// Stop triggert? Herunterzählen? Bei 0 das Event für wartendes ITAAsioStop() setzen.
if
(
iZeroBlocks
>
0
)
if
((
--
iZeroBlocks
)
==
0
)
SetEvent
(
hStopEvent
);
if
(
iZeroBlocks
>
0
)
if
(
(
--
iZeroBlocks
)
==
0
)
SetEvent
(
hStopEvent
);
// Internen Mutex freigeben
LeaveCriticalSection
(
&
csInternal
);
LeaveCriticalSection
(
&
csInternal
);
// Finally if the driver supports the ASIOOutputReady() optimization,
// do it here, all data are in place
//if (asioDriverInfo.postOutput)
...
...
@@ -460,7 +479,7 @@ ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processN
return
0L
;
}
void
bufferSwitch
(
long
index
,
ASIOBool
processNow
)
{
// the actual processing callback.
void
bufferSwitch
(
long
index
,
ASIOBool
processNow
)
{
// the actual processing callback.
// Beware that this is normally in a seperate thread, hence be sure that
// you take care about thread synchronization. This is omitted here for
// simplicity.
...
...
@@ -471,20 +490,21 @@ void bufferSwitch(long index, ASIOBool processNow) { // the actual processing ca
// to be created though it will only set the timeInfo.samplePosition and
// timeInfo.systemTime fields and the according flags
ASIOTime
timeInfo
;
memset
(
&
timeInfo
,
0
,
sizeof
(
timeInfo
)
);
memset
(
&
timeInfo
,
0
,
sizeof
(
timeInfo
)
);
// Get the time stamp of the buffer, not necessary if no
// synchronization to other media is required
if
(
ASIOGetSamplePosition
(
&
timeInfo
.
timeInfo
.
samplePosition
,
&
timeInfo
.
timeInfo
.
systemTime
)
==
ASE_OK
)
if
(
ASIOGetSamplePosition
(
&
timeInfo
.
timeInfo
.
samplePosition
,
&
timeInfo
.
timeInfo
.
systemTime
)
==
ASE_OK
)
timeInfo
.
timeInfo
.
flags
=
kSystemTimeValid
|
kSamplePositionValid
;
bufferSwitchTimeInfo
(
&
timeInfo
,
index
,
processNow
);
bufferSwitchTimeInfo
(
&
timeInfo
,
index
,
processNow
);
}
void
sampleRateChanged
(
ASIOSampleRate
sRate
)
{
void
sampleRateChanged
(
ASIOSampleRate
)
{
// MessageBox (0, "Callback sampleRateChanged", "Callback sampleRateChanged", MB_OK|MB_SYSTEMMODAL| MB_APPLMODAL );
// Do whatever you need to do if the sample rate changed
// usually this only happens during external sync.
// Audio processing is not stopped by the driver, actual sample rate
...
...
@@ -494,68 +514,69 @@ void sampleRateChanged(ASIOSampleRate sRate) {
}
long
asioMessages
(
long
selector
,
long
value
,
void
*
message
,
double
*
opt
)
{
long
asioMessages
(
long
selector
,
long
value
,
void
*
,
double
*
)
{
// MessageBox (0, "Callback asioMessages", "Callback asioMessages", MB_OK|MB_SYSTEMMODAL| MB_APPLMODAL );
// Currently the parameters "value", "message" and "opt" are not used.
long
ret
=
0
;
switch
(
selector
)
{
case
kAsioSelectorSupported
:
if
(
value
==
kAsioResetRequest
switch
(
selector
)
{
case
kAsioSelectorSupported
:
if
(
value
==
kAsioResetRequest
||
value
==
kAsioEngineVersion
||
value
==
kAsioResyncRequest
||
value
==
kAsioLatenciesChanged
// the following three were added for ASIO 2.0, you don't necessarily have to support them
||
value
==
kAsioSupportsTimeInfo
||
value
==
kAsioSupportsTimeCode
||
value
==
kAsioSupportsInputMonitor
)
ret
=
1L
;
break
;
case
kAsioResetRequest
:
// defer the task and perform the reset of the driver during the next "safe" situation
// You cannot reset the driver right now, as this code is called from the driver.
// Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction
// Afterwards you initialize the driver again.
asioDriverInfo
.
stopped
;
// In this sample the processing will just stop
||
value
==
kAsioSupportsInputMonitor
)
ret
=
1L
;
break
;
case
kAsioResyncRequest
:
// This informs the application, that the driver encountered some non fatal data loss.
// It is used for synchronization purposes of different media.
// Added mainly to work around the Win16Mutex problems in Windows 95/98 with the
// Windows Multimedia system, which could loose data because the Mutex was hold too long
// by another thread.
// However a driver can issue it in other situations, too.
ret
=
1L
;
break
;
case
kAsioLatenciesChanged
:
//MessageBox (0, "Callback sampleRateChanged BEN", "Callback sampleRateChanged BEN ", MB_OK|MB_SYSTEMMODAL| MB_APPLMODAL );
// This will inform the host application that the drivers were latencies changed.
// Beware, it this does not mean that the buffer sizes have changed!
// You might need to update internal delay data.
ret
=
1L
;
break
;
case
kAsioEngineVersion
:
// return the supported ASIO version of the host application
// If a host applications does not implement this selector, ASIO 1.0 is assumed
// by the driver
ret
=
2L
;
break
;
case
kAsioSupportsTimeInfo
:
// informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback
// is supported.
// For compatibility with ASIO 1.0 drivers the host application should always support
// the "old" bufferSwitch method, too.
ret
=
1
;
break
;
case
kAsioSupportsTimeCode
:
// informs the driver wether application is interested in time code info.
// If an application does not need to know about time code, the driver has less work
// to do.
ret
=
0
;
break
;
break
;
case
kAsioResetRequest
:
// defer the task and perform the reset of the driver during the next "safe" situation
// You cannot reset the driver right now, as this code is called from the driver.
// Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction
// Afterwards you initialize the driver again.
asioDriverInfo
.
stopped
;
// In this sample the processing will just stop
ret
=
1L
;
break
;
case
kAsioResyncRequest
:
// This informs the application, that the driver encountered some non fatal data loss.
// It is used for synchronization purposes of different media.
// Added mainly to work around the Win16Mutex problems in Windows 95/98 with the
// Windows Multimedia system, which could loose data because the Mutex was hold too long
// by another thread.
// However a driver can issue it in other situations, too.
ret
=
1L
;
break
;
case
kAsioLatenciesChanged
:
//MessageBox (0, "Callback sampleRateChanged BEN", "Callback sampleRateChanged BEN ", MB_OK|MB_SYSTEMMODAL| MB_APPLMODAL );
// This will inform the host application that the drivers were latencies changed.
// Beware, it this does not mean that the buffer sizes have changed!
// You might need to update internal delay data.
ret
=
1L
;
break
;
case
kAsioEngineVersion
:
// return the supported ASIO version of the host application
// If a host applications does not implement this selector, ASIO 1.0 is assumed
// by the driver
ret
=
2L
;
break
;
case
kAsioSupportsTimeInfo
:
// informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback
// is supported.
// For compatibility with ASIO 1.0 drivers the host application should always support
// the "old" bufferSwitch method, too.
ret
=
1
;
break
;
case
kAsioSupportsTimeCode
:
// informs the driver wether application is interested in time code info.
// If an application does not need to know about time code, the driver has less work
// to do.
ret
=
0
;
break
;
}
return
ret
;
}
...
...
@@ -566,18 +587,19 @@ long asioMessages(long selector, long value, void* message, double* opt) {
| Implementierung der öffentlichen Funktionen |
| |
+-----------------------------------------------+
*/
*/
ITASIO_API
void
ITAsioInitializeLibrary
(
void
)
{
ITASIO_API
void
ITAsioInitializeLibrary
(
void
)
{
if
(
lState
!=
LIBRAW
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO library already initialized"
);
InitializeCriticalSection
(
&
csInternal
);
InitializeCriticalSection
(
&
csExternal
);
if
(
lState
!=
LIBRAW
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO library already initialized"
);
if
(
FAILED
(
hStopEvent
=
CreateEvent
(
NULL
,
TRUE
,
FALSE
,
NULL
)))
ITA_EXCEPT1
(
UNKNOWN
,
"Failed to create mutex"
);
InitializeCriticalSection
(
&
csInternal
);
InitializeCriticalSection
(
&
csExternal
);
if
(
FAILED
(
hStopEvent
=
CreateEvent
(
NULL
,
TRUE
,
FALSE
,
NULL
)
)
)
ITA_EXCEPT1
(
UNKNOWN
,
"Failed to create mutex"
);
// ASIO-Umgebung ermitteln
asioDrivers
=
new
AsioDrivers
();
...
...
@@ -590,40 +612,42 @@ ITASIO_API void ITAsioInitializeLibrary(void) {
// Treibernamen ermitteln und zwischenspeichern
lNumDrivers
=
asioDrivers
->
asioGetNumDev
();
if
(
lNumDrivers
>
0
)
{
asioDriverNames
=
new
char
*
[
lNumDrivers
];
memset
(
asioDriverNames
,
0
,
lNumDrivers
*
sizeof
(
char
*
));
for
(
int
i
=
0
;
i
<
(
int
)
lNumDrivers
;
i
++
)
asioDriverNames
[
i
]
=
new
char
[
32
];
if
(
lNumDrivers
>
0
)
{
asioDriverNames
=
new
char
*
[
lNumDrivers
];
memset
(
asioDriverNames
,
0
,
lNumDrivers
*
sizeof
(
char
*
)
);
for
(
int
i
=
0
;
i
<
(
int
)
lNumDrivers
;
i
++
)
asioDriverNames
[
i
]
=
new
char
[
32
];
asioDrivers
->
getDriverNames
(
asioDriverNames
,
lNumDrivers
);
asioDrivers
->
getDriverNames
(
asioDriverNames
,
lNumDrivers
);
}
// Startzustand setzen
lState
=
LOADED
;
}
ITASIO_API
void
ITAsioFinalizeLibrary
(
void
)
{
ITASIO_API
void
ITAsioFinalizeLibrary
(
void
)
{
// Gar nicht initialisiert? => Kein Fehler
if
(
lState
==
LIBRAW
)
return
;
if
(
lState
==
LIBRAW
)
return
;
if
(
lNumDrivers
>
0
)
{
for
(
int
i
=
0
;
i
<
(
int
)
lNumDrivers
;
i
++
)
delete
[]
asioDriverNames
[
i
];
for
(
int
i
=
0
;
i
<
(
int
)
lNumDrivers
;
i
++
)
delete
[]
asioDriverNames
[
i
];
delete
[]
asioDriverNames
;
asioDriverNames
=
NULL
;
}
// Treiber noch initialisiert? => Implizit abrüumen
if
(
lState
>
LOADED
)
ITAsioFinalizeDriver
();
if
(
lState
>
LOADED
)
ITAsioFinalizeDriver
();
// ASIO-Umgebung und Resourcen freigeben
delete
asioDrivers
;
CloseHandle
(
hStopEvent
);
CloseHandle
(
hStopEvent
);
DeleteCriticalSection
(
&
csInternal
);
DeleteCriticalSection
(
&
csExternal
);
DeleteCriticalSection
(
&
csInternal
);
DeleteCriticalSection
(
&
csExternal
);
lState
=
LIBRAW
;
}
...
...
@@ -634,24 +658,29 @@ ITASIO_API void ITAsioFinalizeLibrary(void) {
#define REQUIRE_STREAMPREP() { if (lState < PREPARED) ITA_EXCEPT1(MODAL_EXCEPTION, "ASIO streaming not prepared"); }
*/
ITASIO_API
long
ITAsioGetNumDrivers
(
void
)
{
if
(
lState
<
LOADED
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO library not initialized"
);
ITASIO_API
long
ITAsioGetNumDrivers
(
void
)
{
if
(
lState
<
LOADED
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO library not initialized"
);
return
lNumDrivers
;
}
ITASIO_API
const
char
*
ITAsioGetDriverName
(
long
lDriverNr
)
{
if
(
lState
<
LOADED
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO library not initialized"
);
ITASIO_API
const
char
*
ITAsioGetDriverName
(
long
lDriverNr
)
{
if
(
lState
<
LOADED
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO library not initialized"
);
// BUGFIX [fwe, 2007-06-24]: Leerer String != NULL
static
const
char
EMPTY_STRING
=
'\0'
;
// Leeren String zurückgeben, falls ungültiger Index
if
((
lDriverNr
<
0
)
||
(
lDriverNr
>=
lNumDrivers
))
return
&
EMPTY_STRING
;
return
asioDriverNames
[
lDriverNr
];
if
(
(
lDriverNr
<
0
)
||
(
lDriverNr
>=
lNumDrivers
)
)
return
&
EMPTY_STRING
;
return
asioDriverNames
[
lDriverNr
];
}
ITASIO_API
const
char
*
ITAsioGetErrorStr
(
ASIOError
ae
)
{
switch
(
ae
)
{
ITASIO_API
const
char
*
ITAsioGetErrorStr
(
ASIOError
ae
)
{
switch
(
ae
)
{
case
ASE_NotPresent
:
// hardware input or output is not present or available
return
"Hardware is not present or available"
;
...
...
@@ -677,21 +706,29 @@ ITASIO_API const char* ITAsioGetErrorStr(ASIOError ae) {
}
}
ITASIO_API
ASIOError
ITAsioInitializeDriver
(
long
lDriverNr
)
{
if
(
lState
<
LOADED
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO library not initialized"
);
if
(
lState
>
LOADED
)
ITA_EXCEPT1
(
MODAL_EXCEPTION
,
"ASIO driver already initialized"
);
ITASIO_API
ASIOError
ITAsioInitializeDriver
(
long
lDriverNr
)
{
if
(
lState
<
LOADED
)