1 /******************************************************************************\
2  * Copyright (c) 2004-2020
3  *
4  * Author(s):
5  *  Volker Fischer
6  *
7  ******************************************************************************
8  *
9  * This program is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License as published by the Free Software
11  * Foundation; either version 2 of the License, or (at your option) any later
12  * version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
22  *
23 \******************************************************************************/
24 
25 #pragma once
26 
27 #include <QMutex>
28 #include <QMessageBox>
29 #include "../src/util.h"
30 #include "../src/global.h"
31 #include "../src/soundbase.h"
32 
33 // copy the ASIO SDK in the llcon/windows directory: "llcon/windows/ASIOSDK2" to
34 // get it work
35 #include "asiosys.h"
36 #include "asio.h"
37 #include "asiodrivers.h"
38 
39 /* Definitions ****************************************************************/
40 // stereo for input and output
41 #define NUM_IN_OUT_CHANNELS 2
42 
43 /* Classes ********************************************************************/
44 class CSound : public CSoundBase
45 {
46     Q_OBJECT
47 
48 public:
49     CSound ( void ( *fpNewCallback ) ( CVector<int16_t>& psData, void* arg ), void* arg, const QString& strMIDISetup, const bool, const QString& );
50 
~CSound()51     virtual ~CSound() { UnloadCurrentDriver(); }
52 
53     virtual int  Init ( const int iNewPrefMonoBufferSize );
54     virtual void Start();
55     virtual void Stop();
56 
OpenDriverSetup()57     virtual void OpenDriverSetup() { ASIOControlPanel(); }
58 
59     // channel selection
GetNumInputChannels()60     virtual int     GetNumInputChannels() { return static_cast<int> ( lNumInChanPlusAddChan ); }
GetInputChannelName(const int iDiD)61     virtual QString GetInputChannelName ( const int iDiD ) { return channelInputName[iDiD]; }
62     virtual void    SetLeftInputChannel ( const int iNewChan );
63     virtual void    SetRightInputChannel ( const int iNewChan );
GetLeftInputChannel()64     virtual int     GetLeftInputChannel() { return vSelectedInputChannels[0]; }
GetRightInputChannel()65     virtual int     GetRightInputChannel() { return vSelectedInputChannels[1]; }
66 
GetNumOutputChannels()67     virtual int     GetNumOutputChannels() { return static_cast<int> ( lNumOutChan ); }
GetOutputChannelName(const int iDiD)68     virtual QString GetOutputChannelName ( const int iDiD ) { return channelInfosOutput[iDiD].name; }
69     virtual void    SetLeftOutputChannel ( const int iNewChan );
70     virtual void    SetRightOutputChannel ( const int iNewChan );
GetLeftOutputChannel()71     virtual int     GetLeftOutputChannel() { return vSelectedOutputChannels[0]; }
GetRightOutputChannel()72     virtual int     GetRightOutputChannel() { return vSelectedOutputChannels[1]; }
73 
GetInOutLatencyMs()74     virtual float GetInOutLatencyMs() { return fInOutLatencyMs; }
75 
76 protected:
77     virtual QString LoadAndInitializeDriver ( QString strDriverName, bool bOpenDriverSetup );
78     virtual void    UnloadCurrentDriver();
79     int             GetActualBufferSize ( const int iDesiredBufferSizeMono );
80     QString         CheckDeviceCapabilities();
81     bool            CheckSampleTypeSupported ( const ASIOSampleType SamType );
82     bool            CheckSampleTypeSupportedForCHMixing ( const ASIOSampleType SamType );
83     void            ResetChannelMapping();
84 
85     int iASIOBufferSizeMono;
86     int iASIOBufferSizeStereo;
87 
88     long         lNumInChan;
89     long         lNumInChanPlusAddChan; // includes additional "added" channels
90     long         lNumOutChan;
91     float        fInOutLatencyMs;
92     CVector<int> vSelectedInputChannels;
93     CVector<int> vSelectedOutputChannels;
94 
95     CVector<int16_t> vecsMultChanAudioSndCrd;
96 
97     QMutex ASIOMutex;
98 
99     // utility functions
100     static int16_t Flip16Bits ( const int16_t iIn );
101     static int32_t Flip32Bits ( const int32_t iIn );
102     static int64_t Flip64Bits ( const int64_t iIn );
103 
104     // audio hardware buffer info
105     struct sHWBufferInfo
106     {
107         long lMinSize;
108         long lMaxSize;
109         long lPreferredSize;
110         long lGranularity;
111     } HWBufferInfo;
112 
113     // ASIO stuff
114     ASIODriverInfo  driverInfo;
115     ASIOBufferInfo  bufferInfos[2 * MAX_NUM_IN_OUT_CHANNELS]; // for input and output buffers -> "2 *"
116     ASIOChannelInfo channelInfosInput[MAX_NUM_IN_OUT_CHANNELS];
117     QString         channelInputName[MAX_NUM_IN_OUT_CHANNELS];
118     ASIOChannelInfo channelInfosOutput[MAX_NUM_IN_OUT_CHANNELS];
119     bool            bASIOPostOutput;
120     ASIOCallbacks   asioCallbacks;
121 
122     // callbacks
123     static void      bufferSwitch ( long index, ASIOBool processNow );
124     static ASIOTime* bufferSwitchTimeInfo ( ASIOTime* timeInfo, long index, ASIOBool processNow );
sampleRateChanged(ASIOSampleRate)125     static void      sampleRateChanged ( ASIOSampleRate ) {}
126     static long      asioMessages ( long selector, long value, void* message, double* opt );
127 
128     char* cDriverNames[MAX_NUMBER_SOUND_CARDS];
129 };
130