Initial import

git-svn-id: http://moon:8086/svn/software/trunk/libsrc/asiosdk2@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2014-07-19 07:44:42 +00:00
commit 562920dd85
83 changed files with 14225 additions and 0 deletions
+253
View File
@@ -0,0 +1,253 @@
{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1031{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}
{\f40\fnil\fcharset77\fprq0{\*\panose 00000000000000000000}Palatino{\*\falt Book Antiqua};}{\f54\froman\fcharset0\fprq0{\*\panose 00000000000000000000}Palatinio;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;
\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;
\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\nowidctlpar\widctlpar\adjustright \fs20\cgrid \snext0 Normal;}{\s1\qj\ri4\keepn\nowidctlpar\widctlpar\tx720\tx9440\adjustright \f40\lang2057\cgrid \sbasedon0 \snext0 heading 1;}{
\s2\ri4\keepn\nowidctlpar\widctlpar\tx720\tx9440\adjustright \b\f40\lang2057\cgrid \sbasedon0 \snext0 heading 2;}{\s3\keepn\nowidctlpar\widctlpar\adjustright \b\f40\fs28\cgrid \sbasedon0 \snext0 heading 3;}{\s4\qc\li20\ri4\keepn\nowidctlpar\widctlpar
\tx720\tx9440\outlinelevel3\adjustright \b\f40\lang2057\cgrid \sbasedon0 \snext0 heading 4;}{\s5\li20\ri4\keepn\nowidctlpar\widctlpar\tx720\tx9440\outlinelevel4\adjustright \b\f40\lang2057\cgrid \sbasedon0 \snext0 heading 5;}{
\s6\ri4\keepn\nowidctlpar\widctlpar\tx2835\outlinelevel5\adjustright \f40\lang2057\cgrid \sbasedon0 \snext0 heading 6;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \b \sbasedon10 Strong;}{\s16\nowidctlpar\widctlpar\adjustright \f40\cgrid
\sbasedon0 \snext16 Body Text;}{\s17\qj\li720\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright \f40\lang2057 \sbasedon0 \snext17 Block Text;}{\s18\ri4\nowidctlpar\widctlpar\tx9440\adjustright \f40\cgrid \sbasedon0 \snext18 Body Text 2;}{
\s19\nowidctlpar\widctlpar\tqc\tx4536\tqr\tx9072\adjustright \fs20\cgrid \sbasedon0 \snext19 header;}{\s20\nowidctlpar\widctlpar\tqc\tx4536\tqr\tx9072\adjustright \fs20\cgrid \sbasedon0 \snext20 footer;}{\*\cs21 \additive \sbasedon10 page number;}}
{\*\listtable{\list\listtemplateid884773172\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat4\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listname ;}\listid147090323}
{\list\listtemplateid169241378\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat2\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-705\li705\jclisttab\tx705 }{\listname ;}\listid189151455}
{\list\listtemplateid-1119817090\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid202835073}
{\list\listtemplateid-1119817090\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid293096607}
{\list\listtemplateid67567631\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid313143283}{\list\listtemplateid744007224
\listsimple{\listlevel\levelnfc2\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'00);}{\levelnumbers\'02;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listname ;}\listid318964504}{\list\listtemplateid-1081582110\listsimple
{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\'01-;}{\levelnumbers;}\f0\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid386730453}{\list\listtemplateid1100000578\listsimple{\listlevel\levelnfc4
\leveljc0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\fbias0 \fi-360\li1065\jclisttab\tx1065 }{\listname ;}\listid395906000}{\list\listtemplateid-1119817090\listsimple{\listlevel\levelnfc23\leveljc0
\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid423957184}{\list\listtemplateid67567631\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0
\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid451368985}{\list\listtemplateid744007224\listsimple{\listlevel\levelnfc2\leveljc0\levelfollow0\levelstartat1\levelspace0
\levelindent0{\leveltext\'03(\'00);}{\levelnumbers\'02;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listname ;}\listid625820396}{\list\listtemplateid-109645698\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0
{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-690\li710\jclisttab\tx710 }{\listname ;}\listid694422911}{\list\listtemplateid2070170092\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext
\'01-;}{\levelnumbers;}\f0\fbias0 \fi-360\li1068\jclisttab\tx1068 }{\listname ;}\listid765418203}{\list\listtemplateid67567631\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers
\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid817956996}{\list\listtemplateid744007224\listsimple{\listlevel\levelnfc2\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'00);}{\levelnumbers\'02;}\fbias0 \fi-720\li720
\jclisttab\tx720 }{\listname ;}\listid840393925}{\list\listtemplateid-1119817090\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360
\jclisttab\tx360 }{\listname ;}\listid877275759}{\list\listtemplateid-1274387274\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-705\li705\jclisttab\tx705 }
{\listname ;}\listid920716126}{\list\listtemplateid-1119817090\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname
;}\listid975985372}{\list\listtemplateid67567631\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid996962552}
{\list\listtemplateid-1119817090\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1029645114}
{\list\listtemplateid-440895742\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-705\li705\jclisttab\tx705 }{\listname ;}\listid1082528144}
{\list\listtemplateid-1081582110\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\'01-;}{\levelnumbers;}\f0\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1340158815}
{\list\listtemplateid-1081582110\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\'01-;}{\levelnumbers;}\f0\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1363288525}
{\list\listtemplateid-527638778\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01-;}{\levelnumbers;}\f0\fbias0 \fi-360\li1070\jclisttab\tx1070 }{\listname ;}\listid1381435271}
{\list\listtemplateid1100000578\listsimple{\listlevel\levelnfc4\leveljc0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\'02\'00);}{\levelnumbers\'01;}\fbias0 \fi-360\li1065\jclisttab\tx1065 }{\listname ;}\listid1422338067}
{\list\listtemplateid67567631\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1492598866}
{\list\listtemplateid744007224\listsimple{\listlevel\levelnfc2\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'00);}{\levelnumbers\'02;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listname ;}\listid1525287283}
{\list\listtemplateid67567631\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1545170217}
{\list\listtemplateid744007224\listsimple{\listlevel\levelnfc2\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03(\'00);}{\levelnumbers\'02;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listname ;}\listid1572500047}
{\list\listtemplateid-1081582110\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\'01-;}{\levelnumbers;}\f0\fbias0 \fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1583635338}
{\list\listtemplateid67567631\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1683580072}{\list\listtemplateid67567631
\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li360\jclisttab\tx360 }{\listname ;}\listid1709181519}{\list\listtemplateid838521518\listsimple{\listlevel
\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-705\li705\jclisttab\tx705 }{\listname ;}\listid2102330982}{\list\listtemplateid1155668642\listsimple{\listlevel\levelnfc0\leveljc0
\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\f0\fs20\fbias0 \fi-705\li705\jclisttab\tx705 }{\listname ;}\listid2144618207}}{\*\listoverridetable{\listoverride\listid694422911\listoverridecount0\ls1}
{\listoverride\listid1381435271\listoverridecount0\ls2}{\listoverride\listid996962552\listoverridecount0\ls3}{\listoverride\listid975985372\listoverridecount0\ls4}{\listoverride\listid1683580072\listoverridecount0\ls5}{\listoverride\listid1363288525
\listoverridecount0\ls6}{\listoverride\listid1572500047\listoverridecount0\ls7}{\listoverride\listid1340158815\listoverridecount0\ls8}{\listoverride\listid318964504\listoverridecount0\ls9}{\listoverride\listid1525287283\listoverridecount0\ls10}
{\listoverride\listid625820396\listoverridecount0\ls11}{\listoverride\listid451368985\listoverridecount0\ls12}{\listoverride\listid202835073\listoverridecount0\ls13}{\listoverride\listid1709181519\listoverridecount0\ls14}{\listoverride\listid423957184
\listoverridecount0\ls15}{\listoverride\listid293096607\listoverridecount0\ls16}{\listoverride\listid877275759\listoverridecount0\ls17}{\listoverride\listid840393925\listoverridecount0\ls18}{\listoverride\listid1082528144\listoverridecount0\ls19}
{\listoverride\listid2102330982\listoverridecount0\ls20}{\listoverride\listid2144618207\listoverridecount0\ls21}{\listoverride\listid189151455\listoverridecount0\ls22}{\listoverride\listid386730453\listoverridecount0\ls23}{\listoverride\listid1583635338
\listoverridecount0\ls24}{\listoverride\listid313143283\listoverridecount0\ls25}{\listoverride\listid1029645114\listoverridecount0\ls26}{\listoverride\listid817956996\listoverridecount0\ls27}{\listoverride\listid1422338067\listoverridecount0\ls28}
{\listoverride\listid765418203\listoverridecount0\ls29}{\listoverride\listid395906000\listoverridecount0\ls30}{\listoverride\listid147090323\listoverridecount0\ls31}{\listoverride\listid920716126\listoverridecount0\ls32}{\listoverride\listid1492598866
\listoverridecount0\ls33}{\listoverride\listid1545170217\listoverridecount0\ls34}}{\info{\title Steinberg VST PlugIns SDK Licensing Agreement}{\author Held, Thorsten}{\operator Thorsten Held}{\creatim\yr1999\mo9\dy10\hr18\min3}
{\revtim\yr1999\mo12\dy29\hr20\min50}{\printim\yr1999\mo7\dy8\hr15\min12}{\version3}{\edmins0}{\nofpages6}{\nofwords1418}{\nofchars8073}{\*\company Steinberg}{\nofcharsws0}{\vern73}}\paperw11906\paperh16838\margl1276\margr1276\margt1418\margb1134
\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\hyphcaps0\formshade\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot \fet0\sectd \linex0\headery1440\footery1440\colsx709\sectdefaultcl {\footer \pard\plain \s20\nowidctlpar\widctlpar
\tqc\tx4536\tqr\tx9072\adjustright \fs20\cgrid {\cs21\f54\fs16 Page: }{\field{\*\fldinst {\cs21\f54\fs16 PAGE }}{\fldrslt {\cs21\f54\fs16\lang1024 6}}}{\cs21\f54\fs16 , }{\b\f54\fs16 Steinberg ASIO SDK, Licensing Agreement, }{\b\f54\fs16
{\field{\*\fldinst SYMBOL 211 \\f "Symbol" \\s 8}{\fldrslt\f3\fs16}}}{\b\f54\fs16 1999}{\f54\fs16
\par }}{\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}
{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8
\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s3\qc\keepn\nowidctlpar\widctlpar\outlinelevel2\adjustright \b\f40\fs28\cgrid {
Steinberg ASIO SDK Licensing Agreement
\par }\pard\plain \s16\qc\nowidctlpar\widctlpar\adjustright \f40\cgrid {(Version \rdblquote 2.0 \endash July 1999\'d3)}{\lang2057
\par }\pard\plain \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright \fs20\cgrid {\f40\lang2057
\par }{\f40\fs24\lang2057 between}{\b\f40\fs24\lang2057
\par
\par }\pard\plain \s4\qc\li20\ri4\keepn\nowidctlpar\widctlpar\tx720\tx9440\outlinelevel3\adjustright \b\f40\lang2057\cgrid {STEINBERG SOFT-UND HARDWARE GMBH
\par }\pard\plain \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright \fs20\cgrid {\b\f40\fs24\lang2057
\par }{\f40\fs24\lang2057 residing at
\par }{\b\f40\fs24\lang2057
\par }{\f40\fs24\lang2057 Eiffestr. 596,
\par 20537 Hamburg
\par GERMANY
\par }\pard \qr\li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 - Steinberg -
\par }\pard \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\b\f40\fs24\lang2057 and
\par }\pard \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057
\par }\pard \qc\li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 ..........................................
\par }\pard \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\b\f40\fs24\lang2057
\par }\pard \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 residing at
\par }{\f40\fs28\lang2057 ...............................
\par ...............................
\par ...............................
\par }\pard \qr\li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 - Licensee- }{\f40\fs24
\par }\pard \nowidctlpar\widctlpar\tx709\adjustright {\b\f40\fs24\lang2057
\par }\pard \fi-709\li709\nowidctlpar\widctlpar\tx709\adjustright {\b\caps\f40\fs24\lang2057
\par \'a4 1\tab }{\cs15\b\caps\f40\fs24 Object of the Agreement
\par }{\f40\fs24
\par {\pntext\pard\plain\f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 1.\tab}}\pard \fi-705\li705\nowidctlpar\widctlpar\jclisttab\tx705{\*\pn \pnlvlbody\ilvl0\ls32\pnrnot0\pndec\pnstart1\pnindent705\pnhang{\pntxta .}}\ls32\adjustright {\f40\fs24
The object of this agreement consists of the Steinberg ASIO (Audio Stream I/O) Software Development Kit }{\b\f40\fs24\ul version 2.0,}{\f40\fs24 comprising of documentation, example code, and several ASIO examples. These are described hereinafter as the
}{\b\f40\fs24 "Licensed Software Developer Kit"}{\f40\fs24 .
\par }\pard\plain \s18\fi-709\li709\nowidctlpar\widctlpar\tx709\adjustright \f40\cgrid {2.\tab Steinberg is the holder of all copyrights, rights of ownership, and other rights concerning the Licensed Software Developer Kit.\line
\par }\pard\plain \fi-709\li709\ri4\nowidctlpar\widctlpar\tx709\adjustright \fs20\cgrid {\f40\fs24 3.\tab The }{\b\f40\fs24 Licensed Software Developer Kit}{\f40\fs24\lang2057 contains information about
\par {\pntext\pard\plain\lang2057\cgrid \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \fi-360\li1068\ri4\nowidctlpar\widctlpar\jclisttab\tx1068\tx9440{\*\pn \pnlvlblt\ilvl0\ls29\pnrnot0\pnstart3\pnindent1068\pnhang{\pntxtb -}}\ls29\adjustright {\f40\fs24\lang2057
how to develop an ASIO Driver, and
\par {\pntext\pard\plain\lang2057\cgrid \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \fi-360\li1068\ri4\nowidctlpar\widctlpar\jclisttab\tx1068\tx9440{\*\pn \pnlvlblt\ilvl0\ls29\pnrnot0\pnstart3\pnindent1068\pnhang{\pntxtb -}}\ls29\adjustright {\f40\fs24\lang2057
how to extend an application so that it can host ASIO Drivers, that are developed under Steinberg\rquote s ASIO Specification, either by Steinberg or any Third-Parties.
\par }\pard \li708\ri4\nowidctlpar\widctlpar\tx9440\adjustright {\f40\fs24\lang2057
\par Currently the following computer platforms are supported:
\par }\pard \qj\li708\ri4\nowidctlpar\widctlpar\tx9440\adjustright {\f40\fs24\lang2057 - Apple Macintosh PPC Computers under the Mac OS,
\par - Windows 95, Windows 98, and NT Systems
\par }\pard\plain \s16\nowidctlpar\widctlpar\tx709\adjustright \f40\cgrid {\b\caps\lang2057 \page \'a4 2\tab Granting of Rights\tab
\par }\pard \s16\nowidctlpar\widctlpar\adjustright {\b\lang2057
\par }\pard \s16\fi-709\li709\nowidctlpar\widctlpar\adjustright {1.\tab Steinberg hereby grants to the Licensee a non-exclusive, worldwide, nontransferable license during the term of this agreement to use the ASIO Interface Technology solely:
\par {\pntext\pard\plain\s16 \f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 (i)\tab}}\pard \s16\fi-720\li1428\nowidctlpar\widctlpar\jclisttab\tx1428{\*\pn \pnlvlbody\ilvl0\ls7\pnrnot0\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\ls7\adjustright
{for the development of ASIO Drivers and/or for the development of an application that can host ASIO Drivers,
\par }\pard \s16\li708\nowidctlpar\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {
\par {\pntext\pard\plain\s16 \f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 (ii)\tab}}\pard \s16\fi-720\li1428\nowidctlpar\widctlpar\jclisttab\tx1428{\*\pn \pnlvlbody\ilvl0\ls7\pnrnot0\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}
\ls7\adjustright {to publish a product under his own name that is using parts or all of the Licensed Software Developer Kit.
\par }\pard\plain \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright \fs20\cgrid {
\par {\pntext\pard\plain\f40\lang2057\cgrid \hich\af40\dbch\af0\loch\f40 2.\tab}}\pard \fi-705\li705\ri4\nowidctlpar\widctlpar\jclisttab\tx705\tx9440{\*\pn \pnlvlbody\ilvl0\ls22\pnrnot0\pndec\pnstart2\pnindent705\pnhang{\pntxta .}}\ls22\adjustright {
\f40\fs24\lang2057 The Licensee has no permission to sell, licence, give-away and/or distribute}{\fs24\lang2057 }{\f40\fs24\lang2057 the }{\f40\fs24
ASIO Interface technology or parts of it in anyway, on any medium, including the Internet, to any other person, including sub-licensors of the Licensee or companies where the Licensee has any involvement.}{\f40\fs24\lang2057 }{\f40\fs24
This includes re-working this specification, or reverse-engineering any products based upon this specification. }{\f40\fs24\lang2057
\par }\pard \ri4\nowidctlpar\widctlpar\tx9440{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f40\fs24\lang2057
\par {\pntext\pard\plain\f40\lang2057\cgrid \hich\af40\dbch\af0\loch\f40 3.\tab}}\pard \fi-705\li705\ri4\nowidctlpar\widctlpar\jclisttab\tx705\tx9440{\*\pn \pnlvlbody\ilvl0\ls22\pnrnot0\pndec\pnstart2\pnindent705\pnhang{\pntxta .}}\ls22\adjustright {
\f40\fs24\lang2057
The Licensee recognises the value of the goodwill associated with the mark ASOP Technology and acknowledges that such goodwill exclusively belongs to the benefit of Steinberg and belongs to Steinberg. The Licensee warrants that it will not use the mark AS
I
O Technology on promotional merchandise , with the exception of demo versions of any of his product making use of this SDK. The Licensee warrants that it will not use the mark ASIO Technology on or in connection with products obscene, pornographic, exces
sively violent, or otherwise in poor taste.
\par }\pard \ri4\nowidctlpar\widctlpar\tx9440{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f40\fs24
\par {\pntext\pard\plain\f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 4.\tab}}\pard \fi-705\li705\ri4\nowidctlpar\widctlpar\jclisttab\tx705\tx9440{\*\pn \pnlvlbody\ilvl0\ls22\pnrnot0\pndec\pnstart2\pnindent705\pnhang{\pntxta .}}\ls22\adjustright {\f40\fs24
If the Licensee is developing a product, that is using parts or all of the Licensed Software Developer Kit, and this product is not published under his own name but will be published by another company, the
Licensee is under the obligation to inform the publisher of the resulting product, that he too must be a party to this Licensing Agreement. The publisher has to completely agree with the ASIO SDK Licensing Agreement. If the publisher is not in agreement w
ith these conditions, the publisher is not allowed to distribute this product which is using parts or all of the Licensed Software Developer Kit.
\par }\pard \ri4\nowidctlpar\widctlpar\tx9440{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f40\fs24
\par {\pntext\pard\plain\f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 5.\tab}}\pard \fi-705\li705\ri4\nowidctlpar\widctlpar\jclisttab\tx705\tx9440{\*\pn \pnlvlbody\ilvl0\ls22\pnrnot0\pndec\pnstart2\pnindent705\pnhang{\pntxta .}}\ls22\adjustright {\f40\fs24
If the Licensee is planning to publish a product, that is using parts or all of the Licensed Software Developer Kit, the Licensee is under the obligation to inform Steinberg about it by sending the signed \lquote Steinberg ASIO SDK Licensing Agreement
\rquote to Steinberg, either by mail, or by fax.
\par }\pard \qj\ri4\nowidctlpar\widctlpar\tx9440\adjustright {\f40\fs24\lang2057
\par }\pard \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\b\caps\lang2057
\par }\pard\plain \s16\nowidctlpar\widctlpar\tx709\adjustright \f40\cgrid {\b\caps\lang2057
\par \page \'a4 3\tab Use Of Trademarks
\par }\pard\plain \nowidctlpar\widctlpar\adjustright \fs20\cgrid {
\par }\pard \li705\ri4\nowidctlpar\widctlpar\tx9440\adjustright {\f40\fs24 If the Licensee is publishing a product under his own name that is using parts or all of the Licensed Software Developer Kit, the }{\f40\fs24\lang2057 Licensee shall be under an obli
gation to refer to Steinberg\rquote s copyrights and trademarks in the following way:
\par }\pard\plain \s18\li705\ri4\nowidctlpar\widctlpar\tx9440\adjustright \f40\cgrid {
\par a) Steinberg\rquote s copyright notice should be included in the documentation, regardless of the media used to supply the documentation.
\par }\pard\plain \li705\ri4\nowidctlpar\widctlpar\tx9440\adjustright \fs20\cgrid {\f40\fs24 Copyright notice: \rdblquote }{\f40\fs24\lang2057 ASIO is a trademark of Steinberg Soft- und Hardware GmbH\'d3
\par }{\f40\fs24 b) The ASIO Logo has to appear on packages and promotional material.
\par }\pard \li709\ri4\nowidctlpar\widctlpar\tx709\tx9440\adjustright {\f40\fs24\lang2057 The ASIO Logo artwork and usage guidelines are part of the }{\b\f40\fs24 "Licensed Software Developer Kit" }{\f40\fs24 and}{\b\f40\fs24 }{\f40\fs24\lang2057
are supplied by Steinberg in digital format. Steinberg makes the ASIO Logo Artwork available on Steinberg\rquote s ftp site.
\par }\pard \li705\ri4\nowidctlpar\widctlpar\tx9440\adjustright {\f40\fs24
\par c) In the \lquote about box\rquote of the product in one of the following formats:
\par }\pard \ri4\nowidctlpar\widctlpar\tx993\adjustright {\f40\fs24\lang2057 \tab - ASIO Technology by Steinberg,
\par }\pard \li993\ri4\nowidctlpar\widctlpar\tx9440\adjustright {\f40\fs24\lang2057 - ASIO Interface Technology by Steinberg Soft- und Hardware GmbH.
\par }\pard \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057
\par
\par }\pard \ri4\nowidctlpar\widctlpar\tx709\tx9440\adjustright {\b\caps\f40\fs24\lang2057 \'a4 4\tab Fees and Royalties
\par }\pard \fi-9\ri4\nowidctlpar\widctlpar\tx709\tx9440\adjustright {\f40\fs24\lang2057
\par }\pard \fi-709\li709\ri4\nowidctlpar\widctlpar\tx640\tx9440\adjustright {\f40\fs24\lang2057 \tab \tab The Licensee shall not obligated to pay to Steinberg any fees or royalties with respect to the ASIO Interface technology.
\par }\pard \nowidctlpar\widctlpar\adjustright {\f40\fs24 \line
\par }\pard\plain \s16\nowidctlpar\widctlpar\tx709\adjustright \f40\cgrid {\b\lang2057 \'a4 5\tab }{\b\caps Liability for Consequential Damages
\par }\pard \s16\li708\nowidctlpar\widctlpar\tx709\adjustright {\line
Steinberg will not be liable for any consequential, special, incidental, direct or indirect damages of any kind, including the loss of data, damage of data-storage-devices, or any loss or damage to other programs being used, arising out of the use of
the Licensed Software Developer Kit or any software developed by the Licensee, including any future up-dates.\line \line
\par }\pard\plain \nowidctlpar\widctlpar\adjustright \fs20\cgrid {\b\f40\fs24 \'a4 6\tab }{\b\caps\f40\fs24 Product Warranty}{\caps\f40\fs24
\par
\par }\pard \qj\li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 1.\tab Steinberg licences the ASIO Interface Technology on an "AS IS" basis.
\par }\pard \qj\li720\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 Steinberg makes no warranties, express or implied
, including without limitation the implied warranties of merchantability and fitness for a particular purpose, regarding the ASIO Interface technology or operation and use in combination with the Licensee\rquote
s program. Neither the Licensee, its employees, agents, or Distributors have any right to make any other representation, warranty or promise with respect to the ASIO Interface technology.
\par }\pard \li729\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057
\par }\pard \qj\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 2.\tab In no event shall Steinberg be liable for incidental or consequential damages
\par }\pard \qj\li720\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 arising from the use, or distribution of the ASIO Interface technology by the Licensee, whether theory of contract, product liability or otherwise.
\par }\pard \li729\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 All claims for indemnification for losses by the Licensee itself or by third parties shall be excluded.
\par }\pard \fi-709\li709\nowidctlpar\widctlpar\adjustright {\f40\fs24
\par }\pard\plain \s18\fi-709\li709\nowidctlpar\widctlpar\adjustright \f40\cgrid {3.\tab
Steinberg may release improved versions of the Licensed Software Developer Kit but offers no commitment whatsoever that such releases will occur at anytime or for anybody.
\par }\pard\plain \nowidctlpar\widctlpar\adjustright \fs20\cgrid {\f40\fs24
\par
\par }{\b\caps\f40\fs24 \'a4 7\tab Infringement
\par
\par }\pard \qj\li708\nowidctlpar\widctlpar\adjustright {\f40\fs24 Steinberg represents and warrants that, as of the date of this Agreement, it is not aware of any claim or action alleging that ASIO, the ASIO Interface Technology, or the content of the }{
\b\f40\fs24 Licensed Software Developer Kit }{\f40\fs24 infringes any third party intellectual property right. Steinberg, however, disclaims any obligation
of defense or indemnify of the Licensee or its customer with respect to any such claim or action, or otherwise arising out of this agreement. Steinberg shall have no liability arising out of any such actual or alleged intellectual property infringement.
\par The Licensee, however, shall promptly notify Steinberg, in writing, of each such infringement claim of which the Licensee becomes aware.
\par }\pard \nowidctlpar\widctlpar\adjustright {\f40\fs24
\par }\pard \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\b\f40\fs24\lang2057
\par }\pard \fi-20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\b\f40\fs24\lang2057 \'a4 8\tab RELATIONSHIP BETWEEN THE TWO PARTIES
\par }\pard \qj\li720\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057
\par Nothing stated in this Agreement will be construed as creating the relationships of joint ventures, partners, principal, agent or whatsoever. The Licensee shall not be entitled to represent Steinberg or to make statements on its behalf.
\par }\pard \qj\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057
\par
\par }\pard \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\b\f40\fs24\lang2057 \'a4 9\tab TERM OF THE AGREEMENT
\par }\pard \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\b\f40\fs24\lang2057
\par }{\f40\fs24\lang2057 1.\tab The Agreement shall run for a unlimited period.
\par }\pard \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057
\par }\pard \qj\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057 2.\tab If the Licensee is in breach of any of its obligations set out in this agreement,
\par }\pard \qj\li720\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\fs24\lang2057
Steinberg shall be entitled to terminate this agreement immediately in writing and inform the Licensee verbally about it. In such a case, this license and all the rights granted to the Licensee herein shall immediately cease.}{\b\f40\fs24\lang2057
\par }\pard \nowidctlpar\widctlpar\adjustright {\f40\fs24 \line
\par }\pard \nowidctlpar\widctlpar\tx709\adjustright {\b\caps\f40\fs24 \'a4 10\tab }{\b\caps\fs24\expnd0\expndtw-3 Final provisions}{\f40 \line
\par {\pntext\pard\plain\f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 1.\tab}}\pard \fi-705\li705\nowidctlpar\widctlpar\jclisttab\tx705{\*\pn \pnlvlbody\ilvl0\ls20\pnrnot0\pndec\pnstart1\pnindent705\pnhang{\pntxta .}}\ls20\adjustright {\f40\fs24
This agreement and the interpreta\-tion thereof}{\f40 }{\f40\fs24 shall be exclusively subject to the laws of the Federal Republic of Germany.
\par }\pard \nowidctlpar\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f40\fs24
\par {\pntext\pard\plain\f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 2.\tab}}\pard \fi-705\li705\nowidctlpar\widctlpar\jclisttab\tx705{\*\pn \pnlvlbody\ilvl0\ls20\pnrnot0\pndec\pnstart1\pnindent705\pnhang{\pntxta .}}\ls20\adjustright {\f40\fs24
The Licensee declares himself to be in agreement with the use of any personal data obtained through this licensing relationship by Steinberg for its own company purposes, and for the purposes of its Company Group, within the meaning of the relevant Data P
rotection laws.
\par }\pard \qj\nowidctlpar\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f40\fs24
\par {\pntext\pard\plain\f40\lang1033\cgrid \hich\af40\dbch\af0\loch\f40 3.\tab}}\pard \qj\fi-705\li705\nowidctlpar\widctlpar\tx709{\*\pn \pnlvlbody\ilvl0\ls20\pnrnot0\pndec\pnstart1\pnindent705\pnhang{\pntxta .}}\ls20\adjustright {\f40\fs24
If any one stipulation of this License contract should be or become invalid, completely or in part, this shall not affect the validity of the remaining stipulations. The parties undertake instead to replace the invalid stipulations wit
h a valid regulation which comes as closely as possible to the purpose originally intended.
\par }\pard \qj\nowidctlpar\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f40\fs24
\par {\pntext\pard\plain\s17 \f40\lang2057 \hich\af40\dbch\af0\loch\f40 4.\tab}}\pard\plain \s17\qj\fi-705\li705\ri4\nowidctlpar\widctlpar\jclisttab\tx705\tx9440{\*\pn \pnlvlbody\ilvl0\ls20\pnrnot0\pndec\pnstart1\pnindent705\pnhang{\pntxta .}}
\ls20\adjustright \f40\lang2057 {Amendments, supplements and notices of termination of this agreement must be made in writing. The rescission of this agreement or an alteration to the requirement of the written form must also be made in writing. Sub\-
sidiary agreements have not been concluded.
\par }\pard \s17\qj\ri4\nowidctlpar\widctlpar\tx9440{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {
\par {\pntext\pard\plain\s17 \f40\lang2057 \hich\af40\dbch\af0\loch\f40 5.\tab}}\pard \s17\qj\fi-705\li705\ri4\nowidctlpar\widctlpar\tx720\tx9440{\*\pn \pnlvlbody\ilvl0\ls20\pnrnot0\pndec\pnstart1\pnindent705\pnhang{\pntxta .}}\ls20\adjustright {
Place of jurisdiction for all disputes is Hamburg. In addition, each party can bring an action against the other party at the general place of jurisdiction of the other party.
\par }\pard \s17\qj\ri4\nowidctlpar\widctlpar\tx9440{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {
\par {\pntext\pard\plain\s17 \f40\lang2057 \hich\af40\dbch\af0\loch\f40 6.\tab}}\pard \s17\qj\fi-705\li705\ri4\nowidctlpar\widctlpar\tx720\tx9440{\*\pn \pnlvlbody\ilvl0\ls20\pnrnot0\pndec\pnstart1\pnindent705\pnhang{\pntxta .}}\ls20\adjustright {
This agreement does not require a specific form (e.g. recording by a notary).
\par }\pard\plain \qj\nowidctlpar\widctlpar\adjustright \fs20\cgrid {\f40\fs24
\par
\par }\pard \ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\lang2057
\par }\pard\plain \s5\li20\ri4\keepn\nowidctlpar\widctlpar\tx720\tx9440\outlinelevel4\adjustright \b\f40\lang2057\cgrid {\caps
\par
\par
\par
\par
\par Steinberg
\par }\pard\plain \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright \fs20\cgrid {\f40\fs24\lang2057 Soft- und Hardware GmbH
\par
\par }\pard \li20\ri4\nowidctlpar\widctlpar\tx720\tx2835\tx9440\adjustright {\f40\fs24\lang2057 By: \tab \tab ..........................................
\par Printed Signature\tab ..........................................
\par Title\tab \tab ..........................................
\par Date executed\tab ..........................................
\par
\par
\par }{\b\f40\fs24\lang2057 - }{\b\caps\f40\fs24\lang2057 Licensee}{\b\f40\fs24\lang2057 -
\par }{\f40\fs24\lang2057
\par By: \tab \tab ..........................................
\par Printed Signature\tab ..........................................
\par Title\tab \tab ..........................................
\par Date executed\tab ..........................................
\par }\pard \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\lang2057
\par }\pard \ri4\nowidctlpar\widctlpar\adjustright {\f40\fs24 \page }{\b\f40\fs24 -Licensee- Technical Contact}{\b\f40\lang2057
\par
\par }\pard\plain \s6\ri4\keepn\nowidctlpar\widctlpar\tx2835\outlinelevel5\adjustright \f40\lang2057\cgrid {Name:\tab -------------------------------------------------------
\par }\pard\plain \ri4\nowidctlpar\widctlpar\adjustright \fs20\cgrid {\f40\fs24\lang2057
\par
\par }\pard\plain \s6\ri4\keepn\nowidctlpar\widctlpar\tx2835\outlinelevel5\adjustright \f40\lang2057\cgrid {Address:\tab -------------------------------------------------------
\par }\pard\plain \ri4\nowidctlpar\widctlpar\adjustright \fs20\cgrid {\f40\fs24\lang2057
\par
\par }\pard\plain \s6\ri4\keepn\nowidctlpar\widctlpar\tx2835\outlinelevel5\adjustright \f40\lang2057\cgrid {Phone:\tab -------------------------------------------------------
\par }\pard\plain \ri4\nowidctlpar\widctlpar\adjustright \fs20\cgrid {\f40\fs24\lang2057
\par
\par }\pard\plain \s6\ri4\keepn\nowidctlpar\widctlpar\tx2835\outlinelevel5\adjustright \f40\lang2057\cgrid {Fax:\tab -------------------------------------------------------
\par }\pard\plain \ri4\nowidctlpar\widctlpar\adjustright \fs20\cgrid {\f40\fs24\lang2057
\par
\par }\pard\plain \s6\ri4\keepn\nowidctlpar\widctlpar\tx2835\outlinelevel5\adjustright \f40\lang2057\cgrid {Email:\tab -------------------------------------------------------
\par }\pard\plain \ri4\nowidctlpar\widctlpar\adjustright \fs20\cgrid {\f40\fs24\lang2057
\par }\pard \li20\ri4\nowidctlpar\widctlpar\tx720\tx9440\adjustright {\f40\lang2057
\par }\pard \qj\nowidctlpar\widctlpar\tx709\adjustright {\f40\fs24
\par }}
Executable
+4855
View File
File diff suppressed because one or more lines are too long
+277
View File
@@ -0,0 +1,277 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
asio.cpp
asio functions entries which translate the
asio interface to the asiodrvr class methods
*/
#include <string.h>
#include "asiosys.h" // platform definition
#include "asio.h"
#if MAC
#include "asiodrvr.h"
#pragma export on
AsioDriver *theAsioDriver = 0;
extern "C"
{
long main()
{
return 'ASIO';
}
#elif WINDOWS
#include "windows.h"
#include "iasiodrv.h"
#include "asiodrivers.h"
IASIO *theAsioDriver = 0;
extern AsioDrivers *asioDrivers;
#elif SGI || SUN || BEOS || LINUX
#include "asiodrvr.h"
static AsioDriver *theAsioDriver = 0;
#endif
//-----------------------------------------------------------------------------------------------------
ASIOError ASIOInit(ASIODriverInfo *info)
{
#if MAC || SGI || SUN || BEOS || LINUX
if(theAsioDriver)
{
delete theAsioDriver;
theAsioDriver = 0;
}
info->driverVersion = 0;
strcpy(info->name, "No ASIO Driver");
theAsioDriver = getDriver();
if(!theAsioDriver)
{
strcpy(info->errorMessage, "Not enough memory for the ASIO driver!");
return ASE_NotPresent;
}
if(!theAsioDriver->init(info->sysRef))
{
theAsioDriver->getErrorMessage(info->errorMessage);
delete theAsioDriver;
theAsioDriver = 0;
return ASE_NotPresent;
}
strcpy(info->errorMessage, "No ASIO Driver Error");
theAsioDriver->getDriverName(info->name);
info->driverVersion = theAsioDriver->getDriverVersion();
return ASE_OK;
#else
info->driverVersion = 0;
strcpy(info->name, "No ASIO Driver");
if(theAsioDriver) // must be loaded!
{
if(!theAsioDriver->init(info->sysRef))
{
theAsioDriver->getErrorMessage(info->errorMessage);
theAsioDriver = 0;
return ASE_NotPresent;
}
strcpy(info->errorMessage, "No ASIO Driver Error");
theAsioDriver->getDriverName(info->name);
info->driverVersion = theAsioDriver->getDriverVersion();
return ASE_OK;
}
return ASE_NotPresent;
#endif // !MAC
}
ASIOError ASIOExit(void)
{
if(theAsioDriver)
{
#if WINDOWS
asioDrivers->removeCurrentDriver();
#else
delete theAsioDriver;
#endif
}
theAsioDriver = 0;
return ASE_OK;
}
ASIOError ASIOStart(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->start();
}
ASIOError ASIOStop(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->stop();
}
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
{
if(!theAsioDriver)
{
*numInputChannels = *numOutputChannels = 0;
return ASE_NotPresent;
}
return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
}
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
{
if(!theAsioDriver)
{
*inputLatency = *outputLatency = 0;
return ASE_NotPresent;
}
return theAsioDriver->getLatencies(inputLatency, outputLatency);
}
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
{
if(!theAsioDriver)
{
*minSize = *maxSize = *preferredSize = *granularity = 0;
return ASE_NotPresent;
}
return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
}
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->canSampleRate(sampleRate);
}
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->getSampleRate(currentRate);
}
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->setSampleRate(sampleRate);
}
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
{
if(!theAsioDriver)
{
*numSources = 0;
return ASE_NotPresent;
}
return theAsioDriver->getClockSources(clocks, numSources);
}
ASIOError ASIOSetClockSource(long reference)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->setClockSource(reference);
}
ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->getSamplePosition(sPos, tStamp);
}
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
{
if(!theAsioDriver)
{
info->channelGroup = -1;
info->type = ASIOSTInt16MSB;
strcpy(info->name, "None");
return ASE_NotPresent;
}
return theAsioDriver->getChannelInfo(info);
}
ASIOError ASIOGetChannelInfoInput(ASIOChannelInfo *info, long idx)
{
info->isInput = 1;
info->isActive = 0;
info->type = 0;
info->channelGroup = 0;
info->channel = idx;
return ASIOGetChannelInfo(info);
}
ASIOError ASIOGetChannelInfoOutput(ASIOChannelInfo *info, long idx)
{
info->isInput = 0;
info->isActive = 0;
info->type = 0;
info->channelGroup = 0;
info->channel = idx;
return ASIOGetChannelInfo(info);
}
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks)
{
if(!theAsioDriver)
{
ASIOBufferInfo *info = bufferInfos;
for(long i = 0; i < numChannels; i++, info++)
info->buffers[0] = info->buffers[1] = 0;
return ASE_NotPresent;
}
return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);
}
ASIOError ASIODisposeBuffers(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->disposeBuffers();
}
ASIOError ASIOControlPanel(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->controlPanel();
}
ASIOError ASIOFuture(long selector, void *opt)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->future(selector, opt);
}
ASIOError ASIOOutputReady(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->outputReady();
}
#if MAC
} // extern "C"
#pragma export off
#endif
Executable
+957
View File
@@ -0,0 +1,957 @@
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
/*
Steinberg Audio Stream I/O API
(c) 1997 - 1999, Steinberg Soft- und Hardware GmbH
ASIO Interface Specification v 2.0
basic concept is an i/o synchronous double-buffer scheme:
on bufferSwitch(index == 0), host will read/write:
after ASIOStart(), the
read first input buffer A (index 0)
| will be invalid (empty)
* ------------------------
|------------------------|-----------------------|
| | |
| Input Buffer A (0) | Input Buffer B (1) |
| | |
|------------------------|-----------------------|
| | |
| Output Buffer A (0) | Output Buffer B (1) |
| | |
|------------------------|-----------------------|
* -------------------------
| before calling ASIOStart(),
write host will have filled output
buffer B (index 1) already
*please* take special care of proper statement of input
and output latencies (see ASIOGetLatencies()), these
control sequencer sync accuracy
*/
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
/*
prototypes summary:
ASIOError ASIOInit(ASIODriverInfo *info);
ASIOError ASIOExit(void);
ASIOError ASIOStart(void);
ASIOError ASIOStop(void);
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);
ASIOError ASIOSetClockSource(long reference);
ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks);
ASIOError ASIODisposeBuffers(void);
ASIOError ASIOControlPanel(void);
void *ASIOFuture(long selector, void *params);
ASIOError ASIOOutputReady(void);
*/
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
#ifndef __ASIO_H
#define __ASIO_H
// force 4 byte alignment
#if defined(_MSC_VER) && !defined(__MWERKS__)
#pragma pack(push,4)
#elif PRAGMA_ALIGN_SUPPORTED
#pragma options align = native
#endif
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Type definitions
//- - - - - - - - - - - - - - - - - - - - - - - - -
// number of samples data type is 64 bit integer
#if NATIVE_INT64
typedef long long int ASIOSamples;
#else
typedef struct ASIOSamples {
unsigned long hi;
unsigned long lo;
} ASIOSamples;
#endif
// Timestamp data type is 64 bit integer,
// Time format is Nanoseconds.
#if NATIVE_INT64
typedef long long int ASIOTimeStamp ;
#else
typedef struct ASIOTimeStamp {
unsigned long hi;
unsigned long lo;
} ASIOTimeStamp;
#endif
// Samplerates are expressed in IEEE 754 64 bit double float,
// native format as host computer
#if IEEE754_64FLOAT
typedef double ASIOSampleRate;
#else
typedef struct ASIOSampleRate {
char ieee[8];
} ASIOSampleRate;
#endif
// Boolean values are expressed as long
typedef long ASIOBool;
enum {
ASIOFalse = 0,
ASIOTrue = 1
};
// Sample Types are expressed as long
typedef long ASIOSampleType;
enum {
ASIOSTInt16MSB = 0,
ASIOSTInt24MSB = 1, // used for 20 bits as well
ASIOSTInt32MSB = 2,
ASIOSTFloat32MSB = 3, // IEEE 754 32 bit float
ASIOSTFloat64MSB = 4, // IEEE 754 64 bit double float
// these are used for 32 bit data buffer, with different alignment of the data inside
// 32 bit PCI bus systems can be more easily used with these
ASIOSTInt32MSB16 = 8, // 32 bit data with 18 bit alignment
ASIOSTInt32MSB18 = 9, // 32 bit data with 18 bit alignment
ASIOSTInt32MSB20 = 10, // 32 bit data with 20 bit alignment
ASIOSTInt32MSB24 = 11, // 32 bit data with 24 bit alignment
ASIOSTInt16LSB = 16,
ASIOSTInt24LSB = 17, // used for 20 bits as well
ASIOSTInt32LSB = 18,
ASIOSTFloat32LSB = 19, // IEEE 754 32 bit float, as found on Intel x86 architecture
ASIOSTFloat64LSB = 20, // IEEE 754 64 bit double float, as found on Intel x86 architecture
// 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
ASIOSTInt32LSB16 = 24, // 32 bit data with 18 bit alignment
ASIOSTInt32LSB18 = 25, // 32 bit data with 18 bit alignment
ASIOSTInt32LSB20 = 26, // 32 bit data with 20 bit alignment
ASIOSTInt32LSB24 = 27 // 32 bit data with 24 bit alignment
};
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Error codes
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef long ASIOError;
enum {
ASE_OK = 0, // This value will be returned whenever the call succeeded
ASE_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls
ASE_NotPresent = -1000, // hardware input or output is not present or available
ASE_HWMalfunction, // hardware is malfunctioning (can be returned by any ASIO function)
ASE_InvalidParameter, // input parameter invalid
ASE_InvalidMode, // hardware is in a bad mode or used in a bad mode
ASE_SPNotAdvancing, // hardware is not running when sample position is inquired
ASE_NoClock, // sample clock or rate cannot be determined or is not present
ASE_NoMemory // not enough memory for completing the request
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Time Info support
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIOTimeCode
{
double speed; // speed relation (fraction of nominal speed)
// optional; set to 0. or 1. if not supported
ASIOSamples timeCodeSamples; // time in samples
unsigned long flags; // some information flags (see below)
char future[64];
} ASIOTimeCode;
typedef enum ASIOTimeCodeFlags
{
kTcValid = 1,
kTcRunning = 1 << 1,
kTcReverse = 1 << 2,
kTcOnspeed = 1 << 3,
kTcStill = 1 << 4,
kTcSpeedValid = 1 << 8
} ASIOTimeCodeFlags;
typedef struct AsioTimeInfo
{
double speed; // absolute speed (1. = nominal)
ASIOTimeStamp systemTime; // system time related to samplePosition, in nanoseconds
// on mac, must be derived from Microseconds() (not UpTime()!)
// on windows, must be derived from timeGetTime()
ASIOSamples samplePosition;
ASIOSampleRate sampleRate; // current rate
unsigned long flags; // (see below)
char reserved[12];
} AsioTimeInfo;
typedef enum AsioTimeInfoFlags
{
kSystemTimeValid = 1, // must always be valid
kSamplePositionValid = 1 << 1, // must always be valid
kSampleRateValid = 1 << 2,
kSpeedValid = 1 << 3,
kSampleRateChanged = 1 << 4,
kClockSourceChanged = 1 << 5
} AsioTimeInfoFlags;
typedef struct ASIOTime // both input/output
{
long reserved[4]; // must be 0
struct AsioTimeInfo timeInfo; // required
struct ASIOTimeCode timeCode; // optional, evaluated if (timeCode.flags & kTcValid)
} ASIOTime;
/*
using time info:
it is recommended to use the new method with time info even if the asio
device does not support timecode; continuous calls to ASIOGetSamplePosition
and ASIOGetSampleRate are avoided, and there is a more defined relationship
between callback time and the time info.
see the example below.
to initiate time info mode, after you have received the callbacks pointer in
ASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo
as the argument. if this returns 1, host has accepted time info mode.
now host expects the new callback bufferSwitchTimeInfo to be used instead
of the old bufferSwitch method. the ASIOTime structure is assumed to be valid
and accessible until the callback returns.
using time code:
if the device supports reading time code, it will call host's asioMessage callback
with kAsioSupportsTimeCode as the selector. it may then fill the according
fields and set the kTcValid flag.
host will call the future method with the kAsioEnableTimeCodeRead selector when
it wants to enable or disable tc reading by the device. you should also support
the kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example).
note:
the AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions.
as a matter of convention, the relationship between the sample
position counter and the time code at buffer switch time is
(ignoring offset between tc and sample pos when tc is running):
on input: sample 0 -> input buffer sample 0 -> time code 0
on output: sample 0 -> output buffer sample 0 -> time code 0
this means that for 'real' calculations, one has to take into account
the according latencies.
example:
ASIOTime asioTime;
in createBuffers()
{
memset(&asioTime, 0, sizeof(ASIOTime));
AsioTimeInfo* ti = &asioTime.timeInfo;
ti->sampleRate = theSampleRate;
ASIOTimeCode* tc = &asioTime.timeCode;
tc->speed = 1.;
timeInfoMode = false;
canTimeCode = false;
if(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1)
{
timeInfoMode = true;
#if kCanTimeCode
if(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1)
canTimeCode = true;
#endif
}
}
void switchBuffers(long doubleBufferIndex, bool processNow)
{
if(timeInfoMode)
{
AsioTimeInfo* ti = &asioTime.timeInfo;
ti->flags = kSystemTimeValid | kSamplePositionValid | kSampleRateValid;
ti->systemTime = theNanoSeconds;
ti->samplePosition = theSamplePosition;
if(ti->sampleRate != theSampleRate)
ti->flags |= kSampleRateChanged;
ti->sampleRate = theSampleRate;
#if kCanTimeCode
if(canTimeCode && timeCodeEnabled)
{
ASIOTimeCode* tc = &asioTime.timeCode;
tc->timeCodeSamples = tcSamples; // tc in samples
tc->flags = kTcValid | kTcRunning | kTcOnspeed; // if so...
}
ASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);
#else
callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);
#endif
}
else
callbacks->bufferSwitch(doubleBufferIndex, ASIOFalse);
}
ASIOError ASIOFuture(long selector, void *params)
{
switch(selector)
{
case kAsioEnableTimeCodeRead:
timeCodeEnabled = true;
return ASE_SUCCESS;
case kAsioDisableTimeCodeRead:
timeCodeEnabled = false;
return ASE_SUCCESS;
case kAsioCanTimeInfo:
return ASE_SUCCESS;
#if kCanTimeCode
case kAsioCanTimeCode:
return ASE_SUCCESS;
#endif
}
return ASE_NotPresent;
};
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// application's audio stream handler callbacks
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIOCallbacks
{
void (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess);
// bufferSwitch indicates that both input and output are to be processed.
// the current buffer half index (0 for A, 1 for B) determines
// - the output buffer that the host should start to fill. the other buffer
// will be passed to output hardware regardless of whether it got filled
// in time or not.
// - the input buffer that is now filled with incoming data. Note that
// because of the synchronicity of i/o, the input always has at
// least one buffer latency in relation to the output.
// directProcess suggests to the host whether it should immedeately
// start processing (directProcess == ASIOTrue), or whether its process
// should be deferred because the call comes from a very low level
// (for instance, a high level priority interrupt), and direct processing
// would cause timing instabilities for the rest of the system. If in doubt,
// directProcess should be set to ASIOFalse.
// Note: bufferSwitch may be called at interrupt time for highest efficiency.
void (*sampleRateDidChange) (ASIOSampleRate sRate);
// gets called when the AudioStreamIO detects a sample rate change
// If sample rate is unknown, 0 is passed (for instance, clock loss
// when externally synchronized).
long (*asioMessage) (long selector, long value, void* message, double* opt);
// generic callback for various purposes, see selectors below.
// note this is only present if the asio version is 2 or higher
ASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);
// new callback with time info. makes ASIOGetSamplePosition() and various
// calls to ASIOGetSampleRate obsolete,
// and allows for timecode sync etc. to be preferred; will be used if
// the driver calls asioMessage with selector kAsioSupportsTimeInfo.
} ASIOCallbacks;
// asioMessage selectors
enum
{
kAsioSelectorSupported = 1, // selector in <value>, returns 1L if supported,
// 0 otherwise
kAsioEngineVersion, // returns engine (host) asio implementation version,
// 2 or higher
kAsioResetRequest, // request driver reset. if accepted, this
// will close the driver (ASIO_Exit() ) and
// re-open it again (ASIO_Init() etc). some
// drivers need to reconfigure for instance
// when the sample rate changes, or some basic
// changes have been made in ASIO_ControlPanel().
// returns 1L; note the request is merely passed
// to the application, there is no way to determine
// if it gets accepted at this time (but it usually
// will be).
kAsioBufferSizeChange, // not yet supported, will currently always return 0L.
// for now, use kAsioResetRequest instead.
// once implemented, the new buffer size is expected
// in <value>, and on success returns 1L
kAsioResyncRequest, // the driver went out of sync, such that
// the timestamp is no longer valid. this
// is a request to re-start the engine and
// slave devices (sequencer). returns 1 for ok,
// 0 if not supported.
kAsioLatenciesChanged, // the drivers latencies have changed. The engine
// will refetch the latencies.
kAsioSupportsTimeInfo, // if host returns true here, it will expect the
// callback bufferSwitchTimeInfo to be called instead
// of bufferSwitch
kAsioSupportsTimeCode, // supports time code reading/writing
kAsioSupportsInputMonitor, // supports input monitoring
kAsioNumMessageSelectors
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
//- - - - - - - - - - - - - - - - - - - - - - - - -
// (De-)Construction
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIODriverInfo
{
long asioVersion; // currently, 2
long driverVersion; // driver specific
char name[32];
char errorMessage[124];
void *sysRef; // on input: system reference
// (Windows: application main window handle, Mac & SGI: 0)
} ASIODriverInfo;
ASIOError ASIOInit(ASIODriverInfo *info);
/* Purpose:
Initialize the AudioStreamIO.
Parameter:
info: pointer to an ASIODriver structure:
- asioVersion:
- on input, the host version. *** Note *** this is 0 for earlier asio
implementations, and the asioMessage callback is implemeted
only if asioVersion is 2 or greater. sorry but due to a design fault
the driver doesn't have access to the host version in ASIOInit :-(
added selector for host (engine) version in the asioMessage callback
so we're ok from now on.
- on return, asio implementation version.
older versions are 1
if you support this version (namely, ASIO_outputReady() )
this should be 2 or higher. also see the note in
ASIO_getTimeStamp() !
- version: on return, the driver version (format is driver specific)
- name: on return, a null-terminated string containing the driver's name
- error message: on return, should contain a user message describing
the type of error that occured during ASIOInit(), if any.
- sysRef: platform specific
Returns:
If neither input nor output is present ASE_NotPresent
will be returned.
ASE_NoMemory, ASE_HWMalfunction are other possible error conditions
*/
ASIOError ASIOExit(void);
/* Purpose:
Terminates the AudioStreamIO.
Parameter:
None.
Returns:
If neither input nor output is present ASE_NotPresent
will be returned.
Notes: this implies ASIOStop() and ASIODisposeBuffers(),
meaning that no host callbacks must be accessed after ASIOExit().
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Start/Stop
//- - - - - - - - - - - - - - - - - - - - - - - - -
ASIOError ASIOStart(void);
/* Purpose:
Start input and output processing synchronously.
This will
- reset the sample counter to zero
- start the hardware (both input and output)
The first call to the hosts' bufferSwitch(index == 0) then tells
the host to read from input buffer A (index 0), and start
processing to output buffer A while output buffer B (which
has been filled by the host prior to calling ASIOStart())
is possibly sounding (see also ASIOGetLatencies())
Parameter:
None.
Returns:
If neither input nor output is present, ASE_NotPresent
will be returned.
If the hardware fails to start, ASE_HWMalfunction will be returned.
Notes:
There is no restriction on the time that ASIOStart() takes
to perform (that is, it is not considered a realtime trigger).
*/
ASIOError ASIOStop(void);
/* Purpose:
Stops input and output processing altogether.
Parameter:
None.
Returns:
If neither input nor output is present ASE_NotPresent
will be returned.
Notes:
On return from ASIOStop(), the driver must in no
case call the hosts' bufferSwitch() routine.
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Inquiry methods and sample rate
//- - - - - - - - - - - - - - - - - - - - - - - - -
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);
/* Purpose:
Returns number of individual input/output channels.
Parameter:
numInputChannels will hold the number of available input channels
numOutputChannels will hold the number of available output channels
Returns:
If no input/output is present ASE_NotPresent will be returned.
If only inputs, or only outputs are available, the according
other parameter will be zero, and ASE_OK is returned.
*/
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);
/* Purpose:
Returns the input and output latencies. This includes
device specific delays, like FIFOs etc.
Parameter:
inputLatency will hold the 'age' of the first sample frame
in the input buffer when the hosts reads it in bufferSwitch()
(this is theoretical, meaning it does not include the overhead
and delay between the actual physical switch, and the time
when bufferSitch() enters).
This will usually be the size of one block in sample frames, plus
device specific latencies.
outputLatency will specify the time between the buffer switch,
and the time when the next play buffer will start to sound.
The next play buffer is defined as the one the host starts
processing after (or at) bufferSwitch(), indicated by the
index parameter (0 for buffer A, 1 for buffer B).
It will usually be either one block, if the host writes directly
to a dma buffer, or two or more blocks if the buffer is 'latched' by
the driver. As an example, on ASIOStart(), the host will have filled
the play buffer at index 1 already; when it gets the callback (with
the parameter index == 0), this tells it to read from the input
buffer 0, and start to fill the play buffer 0 (assuming that now
play buffer 1 is already sounding). In this case, the output
latency is one block. If the driver decides to copy buffer 1
at that time, and pass it to the hardware at the next slot (which
is most commonly done, but should be avoided), the output latency
becomes two blocks instead, resulting in a total i/o latency of at least
3 blocks. As memory access is the main bottleneck in native dsp processing,
and to acheive less latency, it is highly recommended to try to avoid
copying (this is also why the driver is the owner of the buffers). To
summarize, the minimum i/o latency can be acheived if the input buffer
is processed by the host into the output buffer which will physically
start to sound on the next time slice. Also note that the host expects
the bufferSwitch() callback to be accessed for each time slice in order
to retain sync, possibly recursively; if it fails to process a block in
time, it will suspend its operation for some time in order to recover.
Returns:
If no input/output is present ASE_NotPresent will be returned.
*/
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
/* Purpose:
Returns min, max, and preferred buffer sizes for input/output
Parameter:
minSize will hold the minimum buffer size
maxSize will hold the maxium possible buffer size
preferredSize will hold the preferred buffer size (a size which
best fits performance and hardware requirements)
granularity will hold the granularity at which buffer sizes
may differ. Usually, the buffer size will be a power of 2;
in this case, granularity will hold -1 on return, signalling
possible buffer sizes starting from minSize, increased in
powers of 2 up to maxSize.
Returns:
If no input/output is present ASE_NotPresent will be returned.
Notes:
When minimum and maximum buffer size are equal,
the preferred buffer size has to be the same value as well; granularity
should be 0 in this case.
*/
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);
/* Purpose:
Inquires the hardware for the available sample rates.
Parameter:
sampleRate is the rate in question.
Returns:
If the inquired sample rate is not supported, ASE_NoClock will be returned.
If no input/output is present ASE_NotPresent will be returned.
*/
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);
/* Purpose:
Get the current sample Rate.
Parameter:
currentRate will hold the current sample rate on return.
Returns:
If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned.
If no input/output is present ASE_NotPresent will be returned.
Notes:
*/
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);
/* Purpose:
Set the hardware to the requested sample Rate. If sampleRate == 0,
enable external sync.
Parameter:
sampleRate: on input, the requested rate
Returns:
If sampleRate is unknown ASE_NoClock will be returned.
If the current clock is external, and sampleRate is != 0,
ASE_InvalidMode will be returned
If no input/output is present ASE_NotPresent will be returned.
Notes:
*/
typedef struct ASIOClockSource
{
long index; // as used for ASIOSetClockSource()
long associatedChannel; // for instance, S/PDIF or AES/EBU
long associatedGroup; // see channel groups (ASIOGetChannelInfo())
ASIOBool isCurrentSource; // ASIOTrue if this is the current clock source
char name[32]; // for user selection
} ASIOClockSource;
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);
/* Purpose:
Get the available external audio clock sources
Parameter:
clocks points to an array of ASIOClockSource structures:
- index: this is used to identify the clock source
when ASIOSetClockSource() is accessed, should be
an index counting from zero
- associatedInputChannel: the first channel of an associated
input group, if any.
- associatedGroup: the group index of that channel.
groups of channels are defined to seperate for
instance analog, S/PDIF, AES/EBU, ADAT connectors etc,
when present simultaniously. Note that associated channel
is enumerated according to numInputs/numOutputs, means it
is independant from a group (see also ASIOGetChannelInfo())
inputs are associated to a clock if the physical connection
transfers both data and clock (like S/PDIF, AES/EBU, or
ADAT inputs). if there is no input channel associated with
the clock source (like Word Clock, or internal oscillator), both
associatedChannel and associatedGroup should be set to -1.
- isCurrentSource: on exit, ASIOTrue if this is the current clock
source, ASIOFalse else
- name: a null-terminated string for user selection of the available sources.
numSources:
on input: the number of allocated array members
on output: the number of available clock sources, at least
1 (internal clock generator).
Returns:
If no input/output is present ASE_NotPresent will be returned.
Notes:
*/
ASIOError ASIOSetClockSource(long index);
/* Purpose:
Set the audio clock source
Parameter:
index as obtained from an inquiry to ASIOGetClockSources()
Returns:
If no input/output is present ASE_NotPresent will be returned.
If the clock can not be selected because an input channel which
carries the current clock source is active, ASE_InvalidMode
*may* be returned (this depends on the properties of the driver
and/or hardware).
Notes:
Should *not* return ASE_NoClock if there is no clock signal present
at the selected source; this will be inquired via ASIOGetSampleRate().
It should call the host callback procedure sampleRateHasChanged(),
if the switch causes a sample rate change, or if no external clock
is present at the selected source.
*/
ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
/* Purpose:
Inquires the sample position/time stamp pair.
Parameter:
sPos will hold the sample position on return. The sample
position is reset to zero when ASIOStart() gets called.
tStamp will hold the system time when the sample position
was latched.
Returns:
If no input/output is present, ASE_NotPresent will be returned.
If there is no clock, ASE_SPNotAdvancing will be returned.
Notes:
in order to be able to synchronise properly,
the sample position / time stamp pair must refer to the current block,
that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch()
callback and expect the time for the current block. thus, when requested
in the very first bufferSwitch after ASIO_Start(), the sample position
should be zero, and the time stamp should refer to the very time where
the stream was started. it also means that the sample position must be
block aligned. the driver must ensure proper interpolation if the system
time can not be determined for the block position. the driver is responsible
for precise time stamps as it usually has most direct access to lower
level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies()
are essential for precise media synchronization!
*/
typedef struct ASIOChannelInfo
{
long channel; // on input, channel index
ASIOBool isInput; // on input
ASIOBool isActive; // on exit
long channelGroup; // dto
ASIOSampleType type; // dto
char name[32]; // dto
} ASIOChannelInfo;
ASIOError ASIOGetChannelInfoInput(ASIOChannelInfo *info, long idx);
ASIOError ASIOGetChannelInfoOutput(ASIOChannelInfo *info, long idx);
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);
/* Purpose:
retreive information about the nature of a channel
Parameter:
info: pointer to a ASIOChannelInfo structure with
- channel: on input, the channel index of the channel in question.
- isInput: on input, ASIOTrue if info for an input channel is
requested, else output
- channelGroup: on return, the channel group that the channel
belongs to. For drivers which support different types of
channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces,
there should be a reasonable grouping of these types. Groups
are always independant form a channel index, that is, a channel
index always counts from 0 to numInputs/numOutputs regardless
of the group it may belong to.
There will always be at least one group (group 0). Please
also note that by default, the host may decide to activate
channels 0 and 1; thus, these should belong to the most
useful type (analog i/o, if present).
- type: on return, contains the sample type of the channel
- isActive: on return, ASIOTrue if channel is active as it was
installed by ASIOCreateBuffers(), ASIOFalse else
- name: describing the type of channel in question. Used to allow
for user selection, and enabling of specific channels. examples:
"Analog In", "SPDIF Out" etc
Returns:
If no input/output is present ASE_NotPresent will be returned.
Notes:
If possible, the string should be organised such that the first
characters are most significantly describing the nature of the
port, to allow for identification even if the view showing the
port name is too small to display more than 8 characters, for
instance.
*/
//- - - - - - - - - - - - - - - - - - - - - - - - -
// Buffer preparation
//- - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct ASIOBufferInfo
{
ASIOBool isInput; // on input: ASIOTrue: input, else output
long channelNum; // on input: channel index
void *buffers[2]; // on output: double buffer addresses
} ASIOBufferInfo;
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks);
/* Purpose:
Allocates input/output buffers for all input and output channels to be activated.
Parameter:
bufferInfos is a pointer to an array of ASIOBufferInfo structures:
- isInput: on input, ASIOTrue if the buffer is to be allocated
for an input, output buffer else
- channelNum: on input, the index of the channel in question
(counting from 0)
- buffers: on exit, 2 pointers to the halves of the channels' double-buffer.
the size of the buffer(s) of course depend on both the ASIOSampleType
as obtained from ASIOGetChannelInfo(), and bufferSize
numChannels is the sum of all input and output channels to be created;
thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo
structures.
bufferSize selects one of the possible buffer sizes as obtained from
ASIOGetBufferSizes().
callbacks is a pointer to an ASIOCallbacks structure.
Returns:
If not enough memory is available ASE_NoMemory will be returned.
If no input/output is present ASE_NotPresent will be returned.
If bufferSize is not supported, or one or more of the bufferInfos elements
contain invalid settings, ASE_InvalidMode will be returned.
Notes:
If individual channel selection is not possible but requested,
the driver has to handle this. namely, bufferSwitch() will only
have filled buffers of enabled outputs. If possible, processing
and buss activities overhead should be avoided for channels which
were not enabled here.
*/
ASIOError ASIODisposeBuffers(void);
/* Purpose:
Releases all buffers for the device.
Parameter:
None.
Returns:
If no buffer were ever prepared, ASE_InvalidMode will be returned.
If no input/output is present ASE_NotPresent will be returned.
Notes:
This implies ASIOStop().
*/
ASIOError ASIOControlPanel(void);
/* Purpose:
request the driver to start a control panel component
for device specific user settings. This will not be
accessed on some platforms (where the component is accessed
instead).
Parameter:
None.
Returns:
If no panel is available ASE_NotPresent will be returned.
Actually, the return code is ignored.
Notes:
if the user applied settings which require a re-configuration
of parts or all of the enigine and/or driver (such as a change of
the block size), the asioMessage callback can be used (see
ASIO_Callbacks).
*/
ASIOError ASIOFuture(long selector, void *params);
/* Purpose:
various
Parameter:
selector: operation Code as to be defined. zero is reserved for
testing purposes.
params: depends on the selector; usually pointer to a structure
for passing and retreiving any type and amount of parameters.
Returns:
the return value is also selector dependant. if the selector
is unknown, ASE_InvalidParameter should be returned to prevent
further calls with this selector. on success, ASE_SUCCESS
must be returned (note: ASE_OK is *not* sufficient!)
Notes:
see selectors defined below.
*/
enum
{
kAsioEnableTimeCodeRead = 1, // no arguments
kAsioDisableTimeCodeRead, // no arguments
kAsioSetInputMonitor, // ASIOInputMonitor* in params
kAsioTransport, // ASIOTransportParameters* in params
kAsioSetInputGain, // ASIOChannelControls* in params, apply gain
kAsioGetInputMeter, // ASIOChannelControls* in params, fill meter
kAsioSetOutputGain, // ASIOChannelControls* in params, apply gain
kAsioGetOutputMeter, // ASIOChannelControls* in params, fill meter
kAsioCanInputMonitor, // no arguments for kAsioCanXXX selectors
kAsioCanTimeInfo,
kAsioCanTimeCode,
kAsioCanTransport,
kAsioCanInputGain,
kAsioCanInputMeter,
kAsioCanOutputGain,
kAsioCanOutputMeter
};
typedef struct ASIOInputMonitor
{
long input; // this input was set to monitor (or off), -1: all
long output; // suggested output for monitoring the input (if so)
long gain; // suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB)
ASIOBool state; // ASIOTrue => on, ASIOFalse => off
long pan; // suggested pan, 0 => all left, 0x7fffffff => right
} ASIOInputMonitor;
typedef struct ASIOChannelControls
{
long channel; // on input, channel index
ASIOBool isInput; // on input
long gain; // on input, ranges 0 thru 0x7fffffff
long meter; // on return, ranges 0 thru 0x7fffffff
char future[32];
} ASIOChannelControls;
typedef struct ASIOTransportParameters
{
long command; // see enum below
ASIOSamples samplePosition;
long track;
long trackSwitches[16]; // 512 tracks on/off
char future[64];
} ASIOTransportParameters;
enum
{
kTransStart = 1,
kTransStop,
kTransLocate, // to samplePosition
kTransPunchIn,
kTransPunchOut,
kTransArmOn, // track
kTransArmOff, // track
kTransMonitorOn, // track
kTransMonitorOff, // track
kTransArm, // trackSwitches
kTransMonitor // trackSwitches
};
ASIOError ASIOOutputReady(void);
/* Purpose:
this tells the driver that the host has completed processing
the output buffers. if the data format required by the hardware
differs from the supported asio formats, but the hardware
buffers are DMA buffers, the driver will have to convert
the audio stream data; as the bufferSwitch callback is
usually issued at dma block switch time, the driver will
have to convert the *previous* host buffer, which increases
the output latency by one block.
when the host finds out that ASIOOutputReady() returns
true, it will issue this call whenever it completed
output processing. then the driver can convert the
host data directly to the dma buffer to be played next,
reducing output latency by one block.
another way to look at it is, that the buffer switch is called
in order to pass the *input* stream to the host, so that it can
process the input into the output, and the output stream is passed
to the driver when the host has completed its process.
Parameter:
None
Returns:
only if the above mentioned scenario is given, and a reduction
of output latency can be acheived by this mechanism, should
ASE_OK be returned. otherwise (and usually), ASE_NotPresent
should be returned in order to prevent further calls to this
function. note that the host may want to determine if it is
to use this when the system is not yet fully initialized, so
ASE_OK should always be returned if the mechanism makes sense.
Notes:
please remeber to adjust ASIOGetLatencies() according to
whether ASIOOutputReady() was ever called or not, if your
driver supports this scenario.
also note that the engine may fail to call ASIO_OutputReady()
in time in overload cases. as already mentioned, bufferSwitch
should be called for every block regardless of whether a block
could be processed in time.
*/
// restore old alignment
#if defined(_MSC_VER) && !defined(__MWERKS__)
#pragma pack(pop)
#elif PRAGMA_ALIGN_SUPPORTED
#pragma options align = reset
#endif
#endif
+139
View File
@@ -0,0 +1,139 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
charlie (May 1996)
asiodrvr.cpp
c++ superclass to implement asio functionality. from this,
you can derive whatever required
*/
#include <string.h>
#include "asiosys.h"
#include "asiodrvr.h"
#if WINDOWS
#error do not use this
AsioDriver::AsioDriver (LPUNKNOWN pUnk, HRESULT *phr) : CUnknown("My AsioDriver", pUnk, phr)
{
}
#else
AsioDriver::AsioDriver()
{
}
#endif
AsioDriver::~AsioDriver()
{
}
ASIOBool AsioDriver::init(void *sysRef)
{
return ASE_NotPresent;
}
void AsioDriver::getDriverName(char *name)
{
strcpy(name, "No Driver");
}
long AsioDriver::getDriverVersion()
{
return 0;
}
void AsioDriver::getErrorMessage(char *string)
{
strcpy(string, "ASIO Driver Implementation Error!");
}
ASIOError AsioDriver::start()
{
return ASE_NotPresent;
}
ASIOError AsioDriver::stop()
{
return ASE_NotPresent;
}
ASIOError AsioDriver::getChannels(long *numInputChannels, long *numOutputChannels)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::getLatencies(long *inputLatency, long *outputLatency)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::getBufferSize(long *minSize, long *maxSize,
long *preferredSize, long *granularity)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::canSampleRate(ASIOSampleRate sampleRate)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::getSampleRate(ASIOSampleRate *sampleRate)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::setSampleRate(ASIOSampleRate sampleRate)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::getClockSources(ASIOClockSource *clocks, long *numSources)
{
*numSources = 0;
return ASE_NotPresent;
}
ASIOError AsioDriver::setClockSource(long reference)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::getChannelInfo(ASIOChannelInfo *info)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::createBuffers(ASIOBufferInfo *channelInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::disposeBuffers()
{
return ASE_NotPresent;
}
ASIOError AsioDriver::controlPanel()
{
return ASE_NotPresent;
}
ASIOError AsioDriver::future(long selector, void *opt)
{
return ASE_NotPresent;
}
ASIOError AsioDriver::outputReady()
{
return ASE_NotPresent;
}
+76
View File
@@ -0,0 +1,76 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
charlie (May 1996)
asiodrvr.h
c++ superclass to implement asio functionality. from this,
you can derive whatever required
*/
#ifndef _asiodrvr_
#define _asiodrvr_
// cpu and os system we are running on
#include "asiosys.h"
// basic "C" interface
#include "asio.h"
class AsioDriver;
extern AsioDriver *getDriver(); // for generic constructor
#if WINDOWS
#include <windows.h>
#include "combase.h"
#include "iasiodrv.h"
class AsioDriver : public IASIO ,public CUnknown
{
public:
AsioDriver(LPUNKNOWN pUnk, HRESULT *phr);
DECLARE_IUNKNOWN
// Factory method
static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
// IUnknown
virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);
#else
class AsioDriver
{
public:
AsioDriver();
#endif
virtual ~AsioDriver();
virtual ASIOBool init(void* sysRef);
virtual void getDriverName(char *name); // max 32 bytes incl. terminating zero
virtual long getDriverVersion();
virtual void getErrorMessage(char *string); // max 124 bytes incl.
virtual ASIOError start();
virtual ASIOError stop();
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
virtual ASIOError getBufferSize(long *minSize, long *maxSize,
long *preferredSize, long *granularity);
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
virtual ASIOError setClockSource(long reference);
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks);
virtual ASIOError disposeBuffers();
virtual ASIOError controlPanel();
virtual ASIOError future(long selector, void *opt);
virtual ASIOError outputReady();
};
#endif
+82
View File
@@ -0,0 +1,82 @@
#ifndef __asiosys__
#define __asiosys__
#ifdef WIN32
#undef MAC
#define PPC 0
#define WINDOWS 1
#define SGI 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#elif BEOS
#define MAC 0
#define PPC 0
#define WINDOWS 0
#define PC 0
#define SGI 0
#define SUN 0
#define LINUX 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#elif SGI
#define MAC 0
#define PPC 0
#define WINDOWS 0
#define PC 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#else // MAC
#define MAC 1
#define PPC 1
#define WINDOWS 0
#define PC 0
#define SGI 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#endif
#endif
+202
View File
@@ -0,0 +1,202 @@
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
// Base class hierachy for creating COM objects, December 1994
#include <windows.h>
#include "wxdebug.h"
#include "combase.h"
#pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
/* Define the static member variable */
LONG CBaseObject::m_cObjects = 0;
/* Constructor */
CBaseObject::CBaseObject(TCHAR *pName)
{
/* Increment the number of active objects */
InterlockedIncrement(&m_cObjects);
#ifdef DEBUG
m_dwCookie = DbgRegisterObjectCreation(pName);
#endif
}
/* Destructor */
CBaseObject::~CBaseObject()
{
/* Decrement the number of objects active */
InterlockedDecrement(&m_cObjects);
#ifdef DEBUG
DbgRegisterObjectDestruction(m_dwCookie);
#endif
}
/* Constructor */
// We know we use "this" in the initialization list, we also know we don't modify *phr.
#pragma warning( disable : 4355 4100 )
CUnknown::CUnknown(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr)
: CBaseObject(pName)
/* Start the object with a reference count of zero - when the */
/* object is queried for it's first interface this may be */
/* incremented depending on whether or not this object is */
/* currently being aggregated upon */
, m_cRef(0)
/* Set our pointer to our IUnknown interface. */
/* If we have an outer, use its, otherwise use ours. */
/* This pointer effectivly points to the owner of */
/* this object and can be accessed by the GetOwner() method. */
, m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
/* Why the double cast? Well, the inner cast is a type-safe cast */
/* to pointer to a type from which we inherit. The second is */
/* type-unsafe but works because INonDelegatingUnknown "behaves */
/* like" IUnknown. (Only the names on the methods change.) */
{
// Everything we need to do has been done in the initializer list
}
#pragma warning( default : 4355 4100 )
/* QueryInterface */
STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
CheckPointer(ppv,E_POINTER);
ValidateReadWritePtr(ppv,sizeof(PVOID));
/* We know only about IUnknown */
if (riid == IID_IUnknown) {
GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
return NOERROR;
} else {
*ppv = NULL;
return E_NOINTERFACE;
}
}
/* We have to ensure that we DON'T use a max macro, since these will typically */
/* lead to one of the parameters being evaluated twice. Since we are worried */
/* about concurrency, we can't afford to access the m_cRef twice since we can't */
/* afford to run the risk that its value having changed between accesses. */
#ifdef max
#undef max
#endif
template<class T> inline static T max( const T & a, const T & b )
{
return a > b ? a : b;
}
/* AddRef */
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
{
LONG lRef = InterlockedIncrement( &m_cRef );
ASSERT(lRef > 0);
DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"),
m_dwCookie, m_cRef));
return max(ULONG(m_cRef), 1ul);
}
/* Release */
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
{
/* If the reference count drops to zero delete ourselves */
LONG lRef = InterlockedDecrement( &m_cRef );
ASSERT(lRef >= 0);
DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"),
m_dwCookie, m_cRef));
if (lRef == 0) {
// COM rules say we must protect against re-entrancy.
// If we are an aggregator and we hold our own interfaces
// on the aggregatee, the QI for these interfaces will
// addref ourselves. So after doing the QI we must release
// a ref count on ourselves. Then, before releasing the
// private interface, we must addref ourselves. When we do
// this from the destructor here it will result in the ref
// count going to 1 and then back to 0 causing us to
// re-enter the destructor. Hence we add an extra refcount here
// once we know we will delete the object.
// for an example aggregator see filgraph\distrib.cpp.
m_cRef++;
delete this;
return ULONG(0);
} else {
return max(ULONG(m_cRef), 1ul);
}
}
/* Return an interface pointer to a requesting client
performing a thread safe AddRef as necessary */
HRESULT CUnknown::GetInterface(LPUNKNOWN pUnk, void **ppv)
{
CheckPointer(ppv, E_POINTER);
*ppv = pUnk;
pUnk->AddRef();
return NOERROR;
}
/* Compares two interfaces and returns TRUE if they are on the same object */
BOOL IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
{
/* Different objects can't have the same interface pointer for
any interface
*/
if (pFirst == pSecond) {
return TRUE;
}
/* OK - do it the hard way - check if they have the same
IUnknown pointers - a single object can only have one of these
*/
LPUNKNOWN pUnknown1; // Retrieve the IUnknown interface
LPUNKNOWN pUnknown2; // Retrieve the other IUnknown interface
HRESULT hr; // General OLE return code
ASSERT(pFirst);
ASSERT(pSecond);
/* See if the IUnknown pointers match */
hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
ASSERT(SUCCEEDED(hr));
ASSERT(pUnknown1);
hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
ASSERT(SUCCEEDED(hr));
ASSERT(pUnknown2);
/* Release the extra interfaces we hold */
pUnknown1->Release();
pUnknown2->Release();
return (pUnknown1 == pUnknown2);
}
+281
View File
@@ -0,0 +1,281 @@
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
// Base class hierachy for creating COM objects, December 1994
/*
a. Derive your COM object from CUnknown
b. Make a static CreateInstance function that takes an LPUNKNOWN, an HRESULT *
and a TCHAR *. The LPUNKNOWN defines the object to delegate IUnknown calls
to. The HRESULT * allows error codes to be passed around constructors and
the TCHAR * is a descriptive name that can be printed on the debugger.
It is important that constructors only change the HRESULT * if they have
to set an ERROR code, if it was successful then leave it alone or you may
overwrite an error code from an object previously created.
When you call a constructor the descriptive name should be in static store
as we do not copy the string. To stop large amounts of memory being used
in retail builds by all these static strings use the NAME macro,
CMyFilter = new CImplFilter(NAME("My filter"),pUnknown,phr);
if (FAILED(hr)) {
return hr;
}
In retail builds NAME(_x_) compiles to NULL, the base CBaseObject class
knows not to do anything with objects that don't have a name.
c. Have a constructor for your object that passes the LPUNKNOWN, HRESULT * and
TCHAR * to the CUnknown constructor. You can set the HRESULT if you have an
error, or just simply pass it through to the constructor.
The object creation will fail in the class factory if the HRESULT indicates
an error (ie FAILED(HRESULT) == TRUE)
d. Create a FactoryTemplate with your object's class id and CreateInstance
function.
Then (for each interface) either
Multiple inheritance
1. Also derive it from ISomeInterface
2. Include DECLARE_IUNKNOWN in your class definition to declare
implementations of QueryInterface, AddRef and Release that
call the outer unknown
3. Override NonDelegatingQueryInterface to expose ISomeInterface by
code something like
if (riid == IID_ISomeInterface) {
return GetInterface((ISomeInterface *) this, ppv);
} else {
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
4. Declare and implement the member functions of ISomeInterface.
or: Nested interfaces
1. Declare a class derived from CUnknown
2. Include DECLARE_IUNKNOWN in your class definition
3. Override NonDelegatingQueryInterface to expose ISomeInterface by
code something like
if (riid == IID_ISomeInterface) {
return GetInterface((ISomeInterface *) this, ppv);
} else {
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
4. Implement the member functions of ISomeInterface. Use GetOwner() to
access the COM object class.
And in your COM object class:
5. Make the nested class a friend of the COM object class, and declare
an instance of the nested class as a member of the COM object class.
NOTE that because you must always pass the outer unknown and an hResult
to the CUnknown constructor you cannot use a default constructor, in
other words you will have to make the member variable a pointer to the
class and make a NEW call in your constructor to actually create it.
6. override the NonDelegatingQueryInterface with code like this:
if (riid == IID_ISomeInterface) {
return m_pImplFilter->
NonDelegatingQueryInterface(IID_ISomeInterface, ppv);
} else {
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
You can have mixed classes which support some interfaces via multiple
inheritance and some via nested classes
*/
#ifndef __COMBASE__
#define __COMBASE__
/* The DLLENTRY module initialises the module handle on loading */
extern HINSTANCE g_hInst;
/* On DLL load remember which platform we are running on */
extern DWORD g_amPlatform;
extern OSVERSIONINFO g_osInfo; // Filled in by GetVersionEx
/* Version of IUnknown that is renamed to allow a class to support both
non delegating and delegating IUnknowns in the same COM object */
DECLARE_INTERFACE(INonDelegatingUnknown)
{
STDMETHOD(NonDelegatingQueryInterface) (THIS_ REFIID, LPVOID *) PURE;
STDMETHOD_(ULONG, NonDelegatingAddRef)(THIS) PURE;
STDMETHOD_(ULONG, NonDelegatingRelease)(THIS) PURE;
};
typedef INonDelegatingUnknown *PNDUNKNOWN;
/* This is the base object class that supports active object counting. As
part of the debug facilities we trace every time a C++ object is created
or destroyed. The name of the object has to be passed up through the class
derivation list during construction as you cannot call virtual functions
in the constructor. The downside of all this is that every single object
constructor has to take an object name parameter that describes it */
class CBaseObject
{
private:
// Disable the copy constructor and assignment by default so you will get
// compiler errors instead of unexpected behaviour if you pass objects
// by value or assign objects.
CBaseObject(const CBaseObject& objectSrc); // no implementation
void operator=(const CBaseObject& objectSrc); // no implementation
private:
static LONG m_cObjects; /* Total number of objects active */
protected:
#ifdef DEBUG
DWORD m_dwCookie; /* Cookie identifying this object */
#endif
public:
/* These increment and decrement the number of active objects */
CBaseObject(TCHAR *pName);
~CBaseObject();
/* Call this to find if there are any CUnknown derived objects active */
static LONG ObjectsActive() {
return m_cObjects;
};
};
/* An object that supports one or more COM interfaces will be based on
this class. It supports counting of total objects for DLLCanUnloadNow
support, and an implementation of the core non delegating IUnknown */
class CUnknown : public INonDelegatingUnknown,
public CBaseObject
{
private:
const LPUNKNOWN m_pUnknown; /* Owner of this object */
protected: /* So we can override NonDelegatingRelease() */
volatile LONG m_cRef; /* Number of reference counts */
public:
CUnknown(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr);
virtual ~CUnknown() {};
/* Return the owner of this object */
LPUNKNOWN GetOwner() const {
return m_pUnknown;
};
/* Called from the class factory to create a new instance, it is
pure virtual so it must be overriden in your derived class */
/* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */
/* Non delegating unknown implementation */
STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) NonDelegatingAddRef();
STDMETHODIMP_(ULONG) NonDelegatingRelease();
/* Return an interface pointer to a requesting client
performing a thread safe AddRef as necessary */
HRESULT GetInterface(LPUNKNOWN pUnk, void **ppv);
};
/* The standard InterlockedXXX functions won't take volatiles */
static inline LONG InterlockedIncrement( volatile LONG * plong )
{ return InterlockedIncrement( const_cast<LONG*>( plong ) ); }
static inline LONG InterlockedDecrement( volatile LONG * plong )
{ return InterlockedDecrement( const_cast<LONG*>( plong ) ); }
static inline LONG InterlockedExchange( volatile LONG * plong, LONG new_value )
{ return InterlockedExchange( const_cast<LONG*>( plong ), new_value ); }
/* A function that can create a new COM object */
typedef CUnknown *(*LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
/* A function (can be NULL) which is called from the DLL entrypoint
routine for each factory template:
bLoading - TRUE on DLL load, FALSE on DLL unload
rclsid - the m_ClsID of the entry
*/
typedef void (*LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
/* Create one of these per object class in an array so that
the default class factory code can create new instances */
class CFactoryTemplate {
public:
const WCHAR *m_Name;
const CLSID *m_ClsID;
LPFNNewCOMObject m_lpfnNew;
LPFNInitRoutine m_lpfnInit;
BOOL IsClassID(REFCLSID rclsid) const {
return (IsEqualCLSID(*m_ClsID,rclsid));
};
CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr) const {
return m_lpfnNew(pUnk, phr);
};
};
/* You must override the (pure virtual) NonDelegatingQueryInterface to return
interface pointers (using GetInterface) to the interfaces your derived
class supports (the default implementation only supports IUnknown) */
#define DECLARE_IUNKNOWN \
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \
return GetOwner()->QueryInterface(riid,ppv); \
}; \
STDMETHODIMP_(ULONG) AddRef() { \
return GetOwner()->AddRef(); \
}; \
STDMETHODIMP_(ULONG) Release() { \
return GetOwner()->Release(); \
};
#endif /* __COMBASE__ */
+14
View File
@@ -0,0 +1,14 @@
#include "asiosys.h"
#if DEBUG
#if MAC
#include <TextUtils.h>
void DEBUGGERMESSAGE(char *string)
{
c2pstr(string);
DebugStr((unsigned char *)string);
}
#else
#error debugmessage
#endif
#endif
+323
View File
@@ -0,0 +1,323 @@
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
//
// classes used to support dll entrypoints for COM objects.
//
// #include "switches.h"
#include <windows.h>
#include "wxdebug.h"
#include "combase.h"
#ifdef DEBUG
#include <tchar.h>
#endif
#include <stdio.h>
extern CFactoryTemplate g_Templates[];
extern int g_cTemplates;
HINSTANCE hinstance = 0;
DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
OSVERSIONINFO g_osInfo;
//
// an instance of this is created by the DLLGetClassObject entrypoint
// it uses the CFactoryTemplate object it is given to support the
// IClassFactory interface
class CClassFactory : public IClassFactory
{
private:
const CFactoryTemplate * m_pTemplate;
ULONG m_cRef;
static int m_cLocked;
public:
CClassFactory(const CFactoryTemplate *);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
STDMETHODIMP_(ULONG)AddRef();
STDMETHODIMP_(ULONG)Release();
// IClassFactory
STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **pv);
STDMETHODIMP LockServer(BOOL fLock);
// allow DLLGetClassObject to know about global server lock status
static BOOL IsLocked() {
return (m_cLocked > 0);
};
};
// process-wide dll locked state
int CClassFactory::m_cLocked = 0;
CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate)
{
m_cRef = 0;
m_pTemplate = pTemplate;
}
STDMETHODIMP CClassFactory::QueryInterface(REFIID riid,void **ppv)
{
CheckPointer(ppv,E_POINTER)
ValidateReadWritePtr(ppv,sizeof(PVOID));
*ppv = NULL;
// any interface on this object is the object pointer.
if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
*ppv = (LPVOID) this;
// AddRef returned interface pointer
((LPUNKNOWN) *ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CClassFactory::Release()
{
LONG rc;
if (--m_cRef == 0) {
delete this;
rc = 0;
} else rc = m_cRef;
return rc;
}
STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,REFIID riid,void **pv)
{
CheckPointer(pv,E_POINTER)
ValidateReadWritePtr(pv,sizeof(void *));
/* Enforce the normal OLE rules regarding interfaces and delegation */
if (pUnkOuter != NULL) {
if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
return ResultFromScode(E_NOINTERFACE);
}
}
/* Create the new object through the derived class's create function */
HRESULT hr = NOERROR;
CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
if (pObj == NULL) {
return E_OUTOFMEMORY;
}
/* Delete the object if we got a construction error */
if (FAILED(hr)) {
delete pObj;
return hr;
}
/* Get a reference counted interface on the object */
/* We wrap the non-delegating QI with NDAddRef & NDRelease. */
/* This protects any outer object from being prematurely */
/* released by an inner object that may have to be created */
/* in order to supply the requested interface. */
pObj->NonDelegatingAddRef();
hr = pObj->NonDelegatingQueryInterface(riid, pv);
pObj->NonDelegatingRelease();
/* Note that if NonDelegatingQueryInterface fails, it will */
/* not increment the ref count, so the NonDelegatingRelease */
/* will drop the ref back to zero and the object will "self-*/
/* destruct". Hence we don't need additional tidy-up code */
/* to cope with NonDelegatingQueryInterface failing. */
if (SUCCEEDED(hr)) {
ASSERT(*pv);
}
return hr;
}
STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
{
if (fLock) {
m_cLocked++;
} else {
m_cLocked--;
}
return NOERROR;
}
// --- COM entrypoints -----------------------------------------
// DllRegisterServer
//called by COM to get the class factory object for a given class
STDAPI DllGetClassObject(REFCLSID rClsID,REFIID riid,void **pv)
{
// DebugBreak();
if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
return E_NOINTERFACE;
}
// traverse the array of templates looking for one with this
// class id
for (int i = 0; i < g_cTemplates; i++) {
const CFactoryTemplate * pT = &g_Templates[i];
if (pT->IsClassID(rClsID)) {
// found a template - make a class factory based on this
// template
*pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
if (*pv == NULL) {
return E_OUTOFMEMORY;
}
((LPUNKNOWN)*pv)->AddRef();
return NOERROR;
}
}
return CLASS_E_CLASSNOTAVAILABLE;
}
//
// Call any initialization routines
//
void DllInitClasses(BOOL bLoading)
{
int i;
// DebugBreak();
// traverse the array of templates calling the init routine
// if they have one
for (i = 0; i < g_cTemplates; i++) {
const CFactoryTemplate * pT = &g_Templates[i];
if (pT->m_lpfnInit != NULL) {
(*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
}
}
}
// called by COM to determine if this dll can be unloaded
// return ok unless there are outstanding objects or a lock requested
// by IClassFactory::LockServer
//
// CClassFactory has a static function that can tell us about the locks,
// and CCOMObject has a static function that can tell us about the active
// object count
STDAPI DllCanUnloadNow()
{
// DebugBreak();
DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
CClassFactory::IsLocked(),
CBaseObject::ObjectsActive()));
if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
return S_FALSE;
}
else {
return S_OK;
}
}
// --- standard WIN32 entrypoints --------------------------------------
//extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
//BOOL WINAPI DllEntryPoint(HINSTANCE hInstance,ULONG ulReason,LPVOID pv)
//BOOL WINAPI DllMain (HINSTANCE hInstance,ULONG ulReason,LPVOID pv)
BOOL WINAPI DllEntryPoint (HINSTANCE hInstance,ULONG ulReason,LPVOID pv)
{
// DebugBreak();
switch (ulReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstance);
DbgInitialise(hInstance);
{
// The platform identifier is used to work out whether
// full unicode support is available or not. Hence the
// default will be the lowest common denominator - i.e. N/A
g_amPlatform = VER_PLATFORM_WIN32_WINDOWS; // win95 assumed in case GetVersionEx fails
g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo);
if (GetVersionEx(&g_osInfo)) {
g_amPlatform = g_osInfo.dwPlatformId;
}
else {
DbgLog((LOG_ERROR, 1, "Failed to get the OS platform, assuming Win95"));
}
}
hinstance = hInstance;
DllInitClasses(TRUE);
break;
case DLL_PROCESS_DETACH:
DllInitClasses(FALSE);
#ifdef DEBUG
if (CBaseObject::ObjectsActive()) {
DbgSetModuleLevel(LOG_MEMORY, 2);
TCHAR szInfo[512];
extern TCHAR m_ModuleName[]; // Cut down module name
TCHAR FullName[_MAX_PATH]; // Load the full path and module name
TCHAR *pName; // Searches from the end for a backslash
GetModuleFileName(NULL,FullName,_MAX_PATH);
pName = _tcsrchr(FullName,'\\');
if (pName == NULL) {
pName = FullName;
}
else {
pName++;
}
DWORD cch = wsprintf(szInfo, TEXT("Executable: %s Pid %x Tid %x. "),
pName, GetCurrentProcessId(), GetCurrentThreadId());
wsprintf(szInfo+cch, TEXT("Module %s, %d objects left active!"),
m_ModuleName, CBaseObject::ObjectsActive());
DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
// If running remotely wait for the Assert to be acknowledged
// before dumping out the object register
DbgDumpObjectRegister();
}
DbgTerminate();
#endif
break;
}
return TRUE;
}
+37
View File
@@ -0,0 +1,37 @@
#include "asiosys.h"
#include "asio.h"
/* Forward Declarations */
#ifndef __ASIODRIVER_FWD_DEFINED__
#define __ASIODRIVER_FWD_DEFINED__
typedef interface IASIO IASIO;
#endif /* __ASIODRIVER_FWD_DEFINED__ */
interface IASIO : public IUnknown
{
virtual ASIOBool init(void *sysHandle) = 0;
virtual void getDriverName(char *name) = 0;
virtual long getDriverVersion() = 0;
virtual void getErrorMessage(char *string) = 0;
virtual ASIOError start() = 0;
virtual ASIOError stop() = 0;
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0;
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0;
virtual ASIOError getBufferSize(long *minSize, long *maxSize,
long *preferredSize, long *granularity) = 0;
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0;
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0;
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0;
virtual ASIOError setClockSource(long reference) = 0;
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0;
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks) = 0;
virtual ASIOError disposeBuffers() = 0;
virtual ASIOError controlPanel() = 0;
virtual ASIOError future(long selector,void *opt) = 0;
virtual ASIOError outputReady() = 0;
};
+332
View File
@@ -0,0 +1,332 @@
#include <windows.h>
#include <stdio.h>
typedef struct keylist
{
HKEY mainKey;
HKEY subKey;
char *keyname;
struct keylist *next;
} KEYLIST, *LPKEYLIST;
#define CLSID_STRING_LEN 100
#define MAX_PATH_LEN 360
#define DEV_ERR_SELFREG -100
#define ERRSREG_MODULE_NOT_FOUND DEV_ERR_SELFREG-1
#define ERRSREG_MODPATH_NOT_FOUND DEV_ERR_SELFREG-2
#define ERRSREG_STRING_FROM_CLSID DEV_ERR_SELFREG-3
#define ERRSREG_CHAR_TO_MULTIBYTE DEV_ERR_SELFREG-4
#define SZREGSTR_DESCRIPTION "Description"
#define SZREGSTR_CLSID "CLSID"
#define SZREGSTR_INPROCSERVER32 "InprocServer32"
#define SZREGSTR_THREADINGMODEL "ThreadingModel"
#define SZREGSTR_SOFTWARE "SOFTWARE"
#define SZREGSTR_ASIO "ASIO"
LONG RegisterAsioDriver (CLSID,char *,char *,char *,char *);
LONG UnregisterAsioDriver (CLSID,char *,char *);
static LONG findRegPath (HKEY,char *);
static LONG createRegPath (HKEY,char *,char *);
static LONG createRegStringValue (HKEY,char *,char *,char *);
static LONG getRegString (HKEY,char *,char *,LPVOID,DWORD);
static LPKEYLIST findAllSubKeys (HKEY,HKEY,DWORD,char *,LPKEYLIST);
static LONG deleteRegPath (HKEY,char *,char *);
static char subkeybuf[MAX_PATH_LEN];
// ------------------------------------------
// Global Functions
// ------------------------------------------
LONG RegisterAsioDriver (CLSID clsid,char *szdllname,char *szregname,char *szasiodesc,char *szthreadmodel)
{
HMODULE hMod;
char szDLLPath[MAX_PATH_LEN];
char szModuleName[MAX_PATH_LEN];
char szregpath[MAX_PATH_LEN];
char szclsid[CLSID_STRING_LEN];
LPOLESTR wszCLSID = NULL;
BOOL newregentry = FALSE;
LONG rc;
hMod = GetModuleHandle(szdllname);
if (!hMod) return ERRSREG_MODULE_NOT_FOUND;
szModuleName[0] = 0;
GetModuleFileName(hMod,szModuleName,MAX_PATH_LEN);
if (!szModuleName[0]) return ERRSREG_MODPATH_NOT_FOUND;
CharLower((LPTSTR)szModuleName);
rc = (LONG)StringFromCLSID(clsid,&wszCLSID);
if (rc != S_OK) return ERRSREG_STRING_FROM_CLSID;
rc = (LONG)WideCharToMultiByte(CP_ACP,0,(LPWSTR)wszCLSID,-1,szclsid,CLSID_STRING_LEN,0,0);
if (!rc) return ERRSREG_CHAR_TO_MULTIBYTE;
sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
rc = findRegPath(HKEY_CLASSES_ROOT,szregpath);
if (rc) {
sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_CLSID,szclsid,SZREGSTR_INPROCSERVER32);
getRegString (HKEY_CLASSES_ROOT,szregpath,0,(LPVOID)szDLLPath,MAX_PATH_LEN);
CharLower((LPTSTR)szDLLPath);
rc = (LONG)strcmp(szDLLPath,szModuleName);
if (rc) {
// delete old regentry
sprintf(szregpath,"%s",SZREGSTR_CLSID);
deleteRegPath(HKEY_CLASSES_ROOT,szregpath,szclsid);
newregentry = TRUE;
}
}
else newregentry = TRUE;
if (newregentry) {
// HKEY_CLASSES_ROOT\CLSID\{...}
sprintf(szregpath,"%s",SZREGSTR_CLSID);
createRegPath (HKEY_CLASSES_ROOT,szregpath,szclsid);
// HKEY_CLASSES_ROOT\CLSID\{...} -> Description
sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
createRegStringValue(HKEY_CLASSES_ROOT,szregpath,0,szasiodesc);
// HKEY_CLASSES_ROOT\CLSID\InProcServer32
sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
createRegPath (HKEY_CLASSES_ROOT,szregpath,SZREGSTR_INPROCSERVER32);
// HKEY_CLASSES_ROOT\CLSID\InProcServer32 -> DLL path
sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_CLSID,szclsid,SZREGSTR_INPROCSERVER32);
createRegStringValue(HKEY_CLASSES_ROOT,szregpath,0,szModuleName);
// HKEY_CLASSES_ROOT\CLSID\InProcServer32 -> ThreadingModel
createRegStringValue(HKEY_CLASSES_ROOT,szregpath,SZREGSTR_THREADINGMODEL,szthreadmodel);
}
// HKEY_LOCAL_MACHINE\SOFTWARE\ASIO
sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
if (rc) {
sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO,szregname);
rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
if (rc) {
sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
deleteRegPath(HKEY_LOCAL_MACHINE,szregpath,szregname);
}
}
else {
// HKEY_LOCAL_MACHINE\SOFTWARE\ASIO
sprintf(szregpath,"%s",SZREGSTR_SOFTWARE);
createRegPath (HKEY_CLASSES_ROOT,szregpath,SZREGSTR_ASIO);
}
// HKEY_LOCAL_MACHINE\SOFTWARE\ASIO\<szregname>
sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
createRegPath (HKEY_LOCAL_MACHINE,szregpath,szregname);
// HKEY_LOCAL_MACHINE\SOFTWARE\ASIO\<szregname> -> CLSID
// HKEY_LOCAL_MACHINE\SOFTWARE\ASIO\<szregname> -> Description
sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO,szregname);
createRegStringValue(HKEY_LOCAL_MACHINE,szregpath,SZREGSTR_CLSID,szclsid);
createRegStringValue(HKEY_LOCAL_MACHINE,szregpath,SZREGSTR_DESCRIPTION,szasiodesc);
return 0;
}
LONG UnregisterAsioDriver (CLSID clsid,char *szdllname,char *szregname)
{
LONG rc;
HMODULE hMod;
char szregpath[MAX_PATH_LEN];
char szModuleName[MAX_PATH_LEN];
char szclsid[CLSID_STRING_LEN];
LPOLESTR wszCLSID = NULL;
hMod = GetModuleHandle(szdllname);
if (!hMod) return ERRSREG_MODULE_NOT_FOUND;
szModuleName[0] = 0;
GetModuleFileName(hMod,szModuleName,MAX_PATH_LEN);
if (!szModuleName[0]) return ERRSREG_MODPATH_NOT_FOUND;
CharLower((LPTSTR)szModuleName);
rc = (LONG)StringFromCLSID(clsid,&wszCLSID) ;
if (rc != S_OK) return ERRSREG_STRING_FROM_CLSID;
rc = (LONG)WideCharToMultiByte(CP_ACP,0,(LPWSTR)wszCLSID,-1,szclsid,CLSID_STRING_LEN,0,0);
if (!rc) return ERRSREG_CHAR_TO_MULTIBYTE;
sprintf(szregpath,"%s\\%s",SZREGSTR_CLSID,szclsid);
rc = findRegPath(HKEY_CLASSES_ROOT,szregpath);
if (rc) {
// delete old regentry
sprintf(szregpath,"%s",SZREGSTR_CLSID);
deleteRegPath(HKEY_CLASSES_ROOT,szregpath,szclsid);
}
// HKEY_LOCAL_MACHINE\SOFTWARE\ASIO
sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
if (rc) {
sprintf(szregpath,"%s\\%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO,szregname);
rc = findRegPath(HKEY_LOCAL_MACHINE,szregpath);
if (rc) {
sprintf(szregpath,"%s\\%s",SZREGSTR_SOFTWARE,SZREGSTR_ASIO);
deleteRegPath(HKEY_LOCAL_MACHINE,szregpath,szregname);
}
}
return 0;
}
// ------------------------------------------
// Local Functions
// ------------------------------------------
static LONG findRegPath (HKEY mainkey,char *szregpath)
{
HKEY hkey;
LONG cr,rc = -1;
if (szregpath) {
if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
RegCloseKey(hkey);
rc = 1;
}
else rc = 0;
}
return rc;
}
static LONG createRegPath (HKEY mainkey,char *szregpath,char *sznewpath)
{
HKEY hkey,hksub;
LONG cr,rc = -1;
char newregpath[MAX_PATH_LEN];
sprintf(newregpath,"%s\\%s",szregpath,sznewpath);
if (!(cr = findRegPath(mainkey,newregpath))) {
if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
if ((cr = RegCreateKey(hkey,sznewpath,&hksub)) == ERROR_SUCCESS) {
RegCloseKey(hksub);
rc = 0;
}
RegCloseKey(hkey);
}
}
else if (cr > 0) rc = 0;
return rc;
}
static LONG createRegStringValue (HKEY mainkey,char *szregpath,char *valname,char *szvalstr)
{
LONG cr,rc = -1;
HKEY hkey;
if (szregpath) {
if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
cr = RegSetValueEx(hkey,(LPCTSTR)valname,0,REG_SZ,(const BYTE *)szvalstr,(DWORD)strlen(szvalstr));
RegCloseKey(hkey);
if (cr == ERROR_SUCCESS) rc = 0;
}
}
return rc;
}
static LONG getRegString (HKEY mainkey,char *szregpath,char *valname,LPVOID pval,DWORD vsize)
{
HKEY hkey;
LONG cr,rc = -1;
DWORD hsize,htype;
if (szregpath) {
if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
cr = RegQueryValueEx(hkey,valname,0,&htype,0,&hsize);
if (cr == ERROR_SUCCESS) {
if (hsize <= vsize) {
cr = RegQueryValueEx(hkey,valname,0,&htype,(LPBYTE)pval,&hsize);
rc = 0;
}
}
RegCloseKey(hkey);
}
}
return rc;
}
static LPKEYLIST findAllSubKeys (HKEY hkey,HKEY hksub,DWORD index,char *keyname,LPKEYLIST kl)
{
HKEY hknew = 0;
char *newkey;
LONG cr;
if (!hksub) {
cr = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_ALL_ACCESS,&hknew);
if (cr != ERROR_SUCCESS) return kl;
}
else hknew = hksub;
cr = RegEnumKey(hknew,index,(LPTSTR)subkeybuf,MAX_PATH_LEN);
if (cr == ERROR_SUCCESS) {
newkey = new char[strlen(subkeybuf)+1];
strcpy(newkey,subkeybuf);
kl = findAllSubKeys(hknew,0,0,newkey,kl);
kl = findAllSubKeys(hkey,hknew,index+1,keyname,kl);
return kl;
}
if (!kl->next) {
kl->next = new KEYLIST[1];
kl = kl->next;
kl->mainKey = hkey;
kl->subKey = hknew;
kl->keyname = keyname;
kl->next = 0;
}
return kl;
}
static LONG deleteRegPath (HKEY mainkey,char *szregpath,char *szdelpath)
{
HKEY hkey;
LONG cr,rc = -1;
KEYLIST klist;
LPKEYLIST pkl,k;
char *keyname = 0;
if ((cr = RegOpenKey(mainkey,szregpath,&hkey)) == ERROR_SUCCESS) {
keyname = new char[strlen(szdelpath)+1];
if (!keyname) {
RegCloseKey(hkey);
return rc;
}
strcpy(keyname,szdelpath);
klist.next = 0;
findAllSubKeys(hkey,0,0,keyname,&klist);
if (klist.next) {
pkl = klist.next;
while (pkl) {
RegCloseKey(pkl->subKey);
cr = RegDeleteKey(pkl->mainKey,pkl->keyname);
delete pkl->keyname;
k = pkl;
pkl = pkl->next;
delete k;
}
rc = 0;
}
RegCloseKey(hkey);
}
return rc;
}
+326
View File
@@ -0,0 +1,326 @@
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
// Debugging facilities, January 1995
#ifndef __WXDEBUG__
#define __WXDEBUG__
// Avoid conflict with MFC
#undef ASSERT
// This library provides fairly straight forward debugging functionality, this
// is split into two main sections. The first is assertion handling, there are
// three types of assertions provided here. The most commonly used one is the
// ASSERT(condition) macro which will pop up a message box including the file
// and line number if the condition evaluates to FALSE. Then there is the
// EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
// still be executed in NON debug builds. The final type of assertion is the
// KASSERT macro which is more suitable for pure (perhaps kernel) filters as
// the condition is printed onto the debugger rather than in a message box.
//
// The other part of the debug module facilties is general purpose logging.
// This is accessed by calling DbgLog(). The function takes a type and level
// field which define the type of informational string you are presenting and
// it's relative importance. The type field can be a combination (one or more)
// of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
// is a DWORD value where zero defines highest important. Use of zero as the
// debug logging level is to be encouraged ONLY for major errors or events as
// they will ALWAYS be displayed on the debugger. Other debug output has it's
// level matched against the current debug output level stored in the registry
// for this module and if less than the current setting it will be displayed.
//
// Each module or executable has it's own debug output level for each of the
// five types. These are read in when the DbgInitialise function is called
// for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
// is loaded, executables must call it explicitely with the module instance
// handle given to them through the WINMAIN entry point. An executable must
// also call DbgTerminate when they have finished to clean up the resources
// the debug library uses, once again this is done automatically for DLLs
// These are the five different categories of logging information
enum { LOG_TIMING = 0x01, // Timing and performance measurements
LOG_TRACE = 0x02, // General step point call tracing
LOG_MEMORY = 0x04, // Memory and object allocation/destruction
LOG_LOCKING = 0x08, // Locking/unlocking of critical sections
LOG_ERROR = 0x10 }; // Debug error notification
enum { CDISP_HEX = 0x01,
CDISP_DEC = 0x02};
// For each object created derived from CBaseObject (in debug builds) we
// create a descriptor that holds it's name (statically allocated memory)
// and a cookie we assign it. We keep a list of all the active objects
// we have registered so that we can dump a list of remaining objects
typedef struct tag_ObjectDesc {
TCHAR *m_pName;
DWORD m_dwCookie;
tag_ObjectDesc *m_pNext;
} ObjectDesc;
#define DLLIMPORT __declspec(dllimport)
#define DLLEXPORT __declspec(dllexport)
#ifdef DEBUG
#define NAME(x) TEXT(x)
// These are used internally by the debug library (PRIVATE)
void DbgInitKeyLevels(HKEY hKey);
void DbgInitGlobalSettings();
void DbgInitModuleSettings();
void DbgInitModuleName();
DWORD DbgRegisterObjectCreation(TCHAR *pObjectName);
BOOL DbgRegisterObjectDestruction(DWORD dwCookie);
// These are the PUBLIC entry points
BOOL DbgCheckModuleLevel(DWORD Type,DWORD Level);
void DbgSetModuleLevel(DWORD Type,DWORD Level);
// Initialise the library with the module handle
void DbgInitialise(HINSTANCE hInst);
void DbgTerminate();
void DbgDumpObjectRegister();
// Display error and logging to the user
void DbgAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
void DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
void DbgKernelAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine);
void DbgLogInfo(DWORD Type,DWORD Level,const TCHAR *pFormat,...);
void DbgOutString(LPCTSTR psz);
// Debug infinite wait stuff
DWORD DbgWaitForSingleObject(HANDLE h);
DWORD DbgWaitForMultipleObjects(DWORD nCount,
CONST HANDLE *lpHandles,
BOOL bWaitAll);
void DbgSetWaitTimeout(DWORD dwTimeout);
#ifdef __strmif_h__
void DisplayType(LPSTR label, const AM_MEDIA_TYPE *pmtIn);
#endif
#define KASSERT(_x_) if (!(_x_)) \
DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
// Break on the debugger without putting up a message box
// message goes to debugger instead
#define KDbgBreak(_x_) \
DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
#define ASSERT(_x_) if (!(_x_)) \
DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
// Put up a message box informing the user of a halt
// condition in the program
#define DbgBreak(_x_) \
DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
#define EXECUTE_ASSERT(_x_) ASSERT(_x_)
#define DbgLog(_x_) DbgLogInfo _x_
// MFC style trace macros
#define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_)));
#define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a));
#define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b));
#define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c));
#define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d));
#define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e));
#else
// Retail builds make public debug functions inert - WARNING the source
// files do not define or build any of the entry points in debug builds
// (public entry points compile to nothing) so if you go trying to call
// any of the private entry points in your source they won't compile
#define NAME(_x_) NULL
#define DbgInitialise(hInst)
#define DbgTerminate()
#define DbgLog(_x_)
#define DbgOutString(psz)
#define DbgRegisterObjectCreation(pObjectName)
#define DbgRegisterObjectDestruction(dwCookie)
#define DbgDumpObjectRegister()
#define DbgCheckModuleLevel(Type,Level)
#define DbgSetModuleLevel(Type,Level)
#define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
#define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
#define DbgSetWaitTimeout(dwTimeout)
#define KDbgBreak(_x_)
#define DbgBreak(_x_)
#define KASSERT(_x_)
#define ASSERT(_x_)
#define EXECUTE_ASSERT(_x_) _x_
// MFC style trace macros
#define NOTE(_x_)
#define NOTE1(_x_,a)
#define NOTE2(_x_,a,b)
#define NOTE3(_x_,a,b,c)
#define NOTE4(_x_,a,b,c,d)
#define NOTE5(_x_,a,b,c,d,e)
#define DisplayType(label, pmtIn)
#endif
// Checks a pointer which should be non NULL - can be used as follows.
#define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
// HRESULT Foo(VOID *pBar)
// {
// CheckPointer(pBar,E_INVALIDARG)
// }
//
// Or if the function returns a boolean
//
// BOOL Foo(VOID *pBar)
// {
// CheckPointer(pBar,FALSE)
// }
// These validate pointers when symbol VFWROBUST is defined
// This will normally be defined in debug not retail builds
#ifdef DEBUG
#define VFWROBUST
#endif
#ifdef VFWROBUST
#define ValidateReadPtr(p,cb) \
{if(IsBadReadPtr((PVOID)p,cb) == TRUE) \
DbgBreak("Invalid read pointer");}
#define ValidateWritePtr(p,cb) \
{if(IsBadWritePtr((PVOID)p,cb) == TRUE) \
DbgBreak("Invalid write pointer");}
#define ValidateReadWritePtr(p,cb) \
{ValidateReadPtr(p,cb) ValidateWritePtr(p,cb)}
#define ValidateStringPtr(p) \
{if(IsBadStringPtr((LPCTSTR)p,INFINITE) == TRUE) \
DbgBreak("Invalid string pointer");}
#define ValidateStringPtrA(p) \
{if(IsBadStringPtrA((LPCSTR)p,INFINITE) == TRUE) \
DbgBreak("Invalid ANSII string pointer");}
#define ValidateStringPtrW(p) \
{if(IsBadStringPtrW((LPCWSTR)p,INFINITE) == TRUE) \
DbgBreak("Invalid UNICODE string pointer");}
#else
#define ValidateReadPtr(p,cb)
#define ValidateWritePtr(p,cb)
#define ValidateReadWritePtr(p,cb)
#define ValidateStringPtr(p)
#define ValidateStringPtrA(p)
#define ValidateStringPtrW(p)
#endif
#ifdef _OBJBASE_H_
// Outputting GUID names. If you want to include the name
// associated with a GUID (eg CLSID_...) then
//
// GuidNames[yourGUID]
//
// Returns the name defined in uuids.h as a string
typedef struct {
TCHAR *szName;
GUID guid;
} GUID_STRING_ENTRY;
class CGuidNameList {
public:
TCHAR *operator [] (const GUID& guid);
};
extern CGuidNameList GuidNames;
#endif
// REMIND macro - generates warning as reminder to complete coding
// (eg) usage:
//
// #pragma message (REMIND("Add automation support"))
#define QUOTE(x) #x
#define QQUOTE(y) QUOTE(y)
#define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
// Hack to display objects in a useful format
//
// eg If you want to display a LONGLONG ll in a debug string do (eg)
//
// DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
class CDispBasic
{
public:
CDispBasic() { m_pString = m_String; };
~CDispBasic();
protected:
PTCHAR m_pString; // normally points to m_String... unless too much data
TCHAR m_String[50];
};
class CDisp : public CDispBasic
{
public:
CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
CDisp(REFCLSID clsid); // Display a GUID
CDisp(double d); // Display a floating point number
#ifdef __strmif_h__
#ifdef __STREAMS__
CDisp(CRefTime t); // Display a Reference Time
#endif
CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name)
#endif // __strmif_h__
~CDisp();
// Implement cast to (LPCTSTR) as parameter to logger
operator LPCTSTR()
{
return (LPCTSTR)m_pString;
};
};
#endif // __WXDEBUG__
+9
View File
@@ -0,0 +1,9 @@
LIBRARY ASIOSample
DESCRIPTION 'ASIO Sample Driver'
PROTMODE
EXPORTS
DllMain
DllGetClassObject
DllCanUnloadNow
DllRegisterServer
DllUnregisterServer
+23
View File
@@ -0,0 +1,23 @@
Asiosample
This sample driver illustrates the implementation of an ASIO driver.
Windows notes:
For Windows a COM implementation is provided. The final driver can be
installed in the system by dragging the asiosample.dll onto the
regsvr32.exe in the windows\system directory.
It is normal that the LNK4104 warning is issued for the following 4
exported symbols:
DllGetClassObject
DllCanUnloadNow
DllRegisterServer
DllUnregisterServer
Macintosh notes:
The supplied project is created with CodeWarrior Pro 5.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+151
View File
@@ -0,0 +1,151 @@
# Microsoft Developer Studio Project File - Name="asiosample" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=asiosample - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "asiosample.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "asiosample.mak" CFG="asiosample - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "asiosample - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "asiosample - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "asiosample - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\Common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386
!ELSEIF "$(CFG)" == "asiosample - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\Common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "asiosample - Win32 Release"
# Name "asiosample - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\asiosample.def
# End Source File
# Begin Source File
SOURCE=..\asiosmpl.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\common\combase.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\common\dllentry.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\common\register.cpp
# End Source File
# Begin Source File
SOURCE=..\wintimer.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\..\common\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\Asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\asiosmpl.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\combase.h
# End Source File
# Begin Source File
SOURCE=..\..\..\common\iasiodrv.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
+29
View File
@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!
###############################################################################
Project: "asiosample"=.\asiosample.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
Binary file not shown.
Binary file not shown.
+37
View File
@@ -0,0 +1,37 @@
<html>
<body>
<pre>
<h1>Erstellungsprotokoll</h1>
<h3>
--------------------Konfiguration: asiosample - Win32 Debug--------------------
</h3>
<h3>Befehlszeilen</h3>
Erstellen der temporären Datei "F:\DOCUME~1\jens\LOCALS~1\Temp\RSP15E.tmp" mit Inhalten
[
/nologo /G5 /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\Common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fp"Debug/asiosample.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
"E:\home\Develop\SDKs\ASIO\asiosdk2\driver\asiosample\asiosmpl.cpp"
]
Creating command line "cl.exe @F:\DOCUME~1\jens\LOCALS~1\Temp\RSP15E.tmp"
Erstellen der temporären Datei "F:\DOCUME~1\jens\LOCALS~1\Temp\RSP15F.tmp" mit Inhalten
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"Debug/asiosample.pdb" /debug /machine:I386 /def:"..\asiosample.def" /out:"Debug/asiosample.dll" /implib:"Debug/asiosample.lib" /pdbtype:sept
.\Debug\asiosmpl.obj
.\Debug\combase.obj
.\Debug\dllentry.obj
.\Debug\register.obj
.\Debug\wintimer.obj
]
Erstellen der Befehlzeile "link.exe @F:\DOCUME~1\jens\LOCALS~1\Temp\RSP15F.tmp"
<h3>Ausgabefenster</h3>
Kompilierung läuft...
asiosmpl.cpp
E:\home\Develop\SDKs\ASIO\asiosdk2\driver\asiosample\asiosmpl.cpp(640) : warning C4244: '=' : Konvertierung von 'double' in 'unsigned long', moeglicher Datenverlust
Linker-Vorgang läuft...
<h3>Ergebnisse</h3>
asiosample.dll - 0 Fehler, 1 Warnung(en)
</pre>
</body>
</html>
+661
View File
@@ -0,0 +1,661 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
charlie (May 1996)
asiosmpl.cpp
sample implementation of asio. can be set to simulate input with some
stupid oscillators.
this driver doesn't output sound at all...
timing is done via the extended time manager on the mac, and
a simple thread on pc.
you may test various configurations by changing the kNumInputs/Outputs,
and kBlockFrames. note that when using wave generation, as i/o is not optimized
at all, it moves quite a bit of memory, too many i/o channels may make it
pretty slow.
if you use this file as a template, make sure to resolve places where the
search string !!! can be found...
*/
#include <stdio.h>
#include <string.h>
#include "asiosmpl.h"
//#include "virtape.h"
//------------------------------------------------------------------------------------------
// extern
void getNanoSeconds(ASIOTimeStamp *time);
// local
double AsioSamples2double (ASIOSamples* samples);
static const double twoRaisedTo32 = 4294967296.;
static const double twoRaisedTo32Reciprocal = 1. / twoRaisedTo32;
//------------------------------------------------------------------------------------------
// on windows, we do the COM stuff.
#if WINDOWS
#include "windows.h"
#include "mmsystem.h"
// class id. !!! NOTE: !!! you will obviously have to create your own class id!
// {188135E1-D565-11d2-854F-00A0C99F5D19}
CLSID IID_ASIO_DRIVER = { 0x188135e1, 0xd565, 0x11d2, { 0x85, 0x4f, 0x0, 0xa0, 0xc9, 0x9f, 0x5d, 0x19 } };
CFactoryTemplate g_Templates[1] = {
{L"ASIOSAMPLE", &IID_ASIO_DRIVER, AsioSample::CreateInstance}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
CUnknown* AsioSample::CreateInstance (LPUNKNOWN pUnk, HRESULT *phr)
{
return (CUnknown*)new AsioSample (pUnk,phr);
};
STDMETHODIMP AsioSample::NonDelegatingQueryInterface (REFIID riid, void ** ppv)
{
if (riid == IID_ASIO_DRIVER)
{
return GetInterface (this, ppv);
}
return CUnknown::NonDelegatingQueryInterface (riid, ppv);
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Register ASIO Driver
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
extern LONG RegisterAsioDriver (CLSID,char *,char *,char *,char *);
extern LONG UnregisterAsioDriver (CLSID,char *,char *);
//
// Server registration, called on REGSVR32.EXE "the dllname.dll"
//
HRESULT _stdcall DllRegisterServer()
{
LONG rc;
char errstr[128];
rc = RegisterAsioDriver (IID_ASIO_DRIVER,"ASIOSample.dll","ASIO Sample Driver","ASIO Sample","Apartment");
if (rc) {
memset(errstr,0,128);
sprintf(errstr,"Register Server failed ! (%d)",rc);
MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"ASIO sample Driver",MB_OK);
return -1;
}
return S_OK;
}
//
// Server unregistration
//
HRESULT _stdcall DllUnregisterServer()
{
LONG rc;
char errstr[128];
rc = UnregisterAsioDriver (IID_ASIO_DRIVER,"ASIOSample.dll","ASIO Sample Driver");
if (rc) {
memset(errstr,0,128);
sprintf(errstr,"Unregister Server failed ! (%d)",rc);
MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"ASIO Korg1212 I/O Driver",MB_OK);
return -1;
}
return S_OK;
}
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
AsioSample::AsioSample (LPUNKNOWN pUnk, HRESULT *phr)
: CUnknown("ASIOSAMPLE", pUnk, phr)
//------------------------------------------------------------------------------------------
#else
// when not on windows, we derive from AsioDriver
AsioSample::AsioSample () : AsioDriver ()
#endif
{
long i;
blockFrames = kBlockFrames;
inputLatency = blockFrames; // typically
outputLatency = blockFrames * 2;
// typically blockFrames * 2; try to get 1 by offering direct buffer
// access, and using asioPostOutput for lower latency
samplePosition = 0;
sampleRate = 44100.;
milliSeconds = (long)((double)(kBlockFrames * 1000) / sampleRate);
active = false;
started = false;
timeInfoMode = false;
tcRead = false;
for (i = 0; i < kNumInputs; i++)
{
inputBuffers[i] = 0;
inMap[i] = 0;
}
#if TESTWAVES
sawTooth = sineWave = 0;
#endif
for (i = 0; i < kNumOutputs; i++)
{
outputBuffers[i] = 0;
outMap[i] = 0;
}
callbacks = 0;
activeInputs = activeOutputs = 0;
toggle = 0;
}
//------------------------------------------------------------------------------------------
AsioSample::~AsioSample ()
{
stop ();
outputClose ();
inputClose ();
disposeBuffers ();
}
//------------------------------------------------------------------------------------------
void AsioSample::getDriverName (char *name)
{
strcpy (name, "Sample ASIO");
}
//------------------------------------------------------------------------------------------
long AsioSample::getDriverVersion ()
{
return 0x00000001L;
}
//------------------------------------------------------------------------------------------
void AsioSample::getErrorMessage (char *string)
{
strcpy (string, errorMessage);
}
//------------------------------------------------------------------------------------------
ASIOBool AsioSample::init (void* sysRef)
{
sysRef = sysRef;
if (active)
return true;
strcpy (errorMessage, "ASIO Driver open Failure!");
if (inputOpen ())
{
if (outputOpen ())
{
active = true;
return true;
}
}
timerOff (); // de-activate 'hardware'
outputClose ();
inputClose ();
return false;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::start ()
{
if (callbacks)
{
started = false;
samplePosition = 0;
theSystemTime.lo = theSystemTime.hi = 0;
toggle = 0;
timerOn (); // activate 'hardware'
started = true;
return ASE_OK;
}
return ASE_NotPresent;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::stop ()
{
started = false;
timerOff (); // de-activate 'hardware'
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::getChannels (long *numInputChannels, long *numOutputChannels)
{
*numInputChannels = kNumInputs;
*numOutputChannels = kNumOutputs;
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::getLatencies (long *_inputLatency, long *_outputLatency)
{
*_inputLatency = inputLatency;
*_outputLatency = outputLatency;
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::getBufferSize (long *minSize, long *maxSize,
long *preferredSize, long *granularity)
{
*minSize = *maxSize = *preferredSize = blockFrames; // allow this size only
*granularity = 0;
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::canSampleRate (ASIOSampleRate sampleRate)
{
if (sampleRate == 44100. || sampleRate == 48000.) // allow these rates only
return ASE_OK;
return ASE_NoClock;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::getSampleRate (ASIOSampleRate *sampleRate)
{
*sampleRate = this->sampleRate;
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::setSampleRate (ASIOSampleRate sampleRate)
{
if (sampleRate != 44100. && sampleRate != 48000.)
return ASE_NoClock;
if (sampleRate != this->sampleRate)
{
this->sampleRate = sampleRate;
asioTime.timeInfo.sampleRate = sampleRate;
asioTime.timeInfo.flags |= kSampleRateChanged;
milliSeconds = (long)((double)(kBlockFrames * 1000) / this->sampleRate);
if (callbacks && callbacks->sampleRateDidChange)
callbacks->sampleRateDidChange (this->sampleRate);
}
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::getClockSources (ASIOClockSource *clocks, long *numSources)
{
// internal
clocks->index = 0;
clocks->associatedChannel = -1;
clocks->associatedGroup = -1;
clocks->isCurrentSource = ASIOTrue;
strcpy(clocks->name, "Internal");
*numSources = 1;
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::setClockSource (long index)
{
if (!index)
{
asioTime.timeInfo.flags |= kClockSourceChanged;
return ASE_OK;
}
return ASE_NotPresent;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::getSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp)
{
tStamp->lo = theSystemTime.lo;
tStamp->hi = theSystemTime.hi;
if (samplePosition >= twoRaisedTo32)
{
sPos->hi = (unsigned long)(samplePosition * twoRaisedTo32Reciprocal);
sPos->lo = (unsigned long)(samplePosition - (sPos->hi * twoRaisedTo32));
}
else
{
sPos->hi = 0;
sPos->lo = (unsigned long)samplePosition;
}
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::getChannelInfo (ASIOChannelInfo *info)
{
if (info->channel < 0 || (info->isInput ? info->channel >= kNumInputs : info->channel >= kNumOutputs))
return ASE_InvalidParameter;
#if WINDOWS
info->type = ASIOSTInt16LSB;
#else
info->type = ASIOSTInt16MSB;
#endif
info->channelGroup = 0;
info->isActive = ASIOFalse;
long i;
if (info->isInput)
{
sprintf(info->name, "Jensis Sample Input %d",info->channel);
for (i = 0; i < activeInputs; i++)
{
if (inMap[i] == info->channel)
{
info->isActive = ASIOTrue;
break;
}
}
}
else
{
sprintf(info->name, "Jensis Sample Output %d",info->channel);
for (i = 0; i < activeOutputs; i++)
{
if (outMap[i] == info->channel)
{
info->isActive = ASIOTrue;
break;
}
}
}
return ASE_OK;
}
//------------------------------------------------------------------------------------------
ASIOError AsioSample::createBuffers (ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks)
{
ASIOBufferInfo *info = bufferInfos;
long i;
bool notEnoughMem = false;
activeInputs = 0;
activeOutputs = 0;
blockFrames = bufferSize;
for (i = 0; i < numChannels; i++, info++)
{
if (info->isInput)
{
if (info->channelNum < 0 || info->channelNum >= kNumInputs)
goto error;
inMap[activeInputs] = info->channelNum;
inputBuffers[activeInputs] = new short[blockFrames * 2]; // double buffer
if (inputBuffers[activeInputs])
{
info->buffers[0] = inputBuffers[activeInputs];
info->buffers[1] = inputBuffers[activeInputs] + blockFrames;
}
else
{
info->buffers[0] = info->buffers[1] = 0;
notEnoughMem = true;
}
activeInputs++;
if (activeInputs > kNumInputs)
{
error:
disposeBuffers();
return ASE_InvalidParameter;
}
}
else // output
{
if (info->channelNum < 0 || info->channelNum >= kNumOutputs)
goto error;
outMap[activeOutputs] = info->channelNum;
outputBuffers[activeOutputs] = new short[blockFrames * 2]; // double buffer
if (outputBuffers[activeOutputs])
{
info->buffers[0] = outputBuffers[activeOutputs];
info->buffers[1] = outputBuffers[activeOutputs] + blockFrames;
}
else
{
info->buffers[0] = info->buffers[1] = 0;
notEnoughMem = true;
}
activeOutputs++;
if (activeOutputs > kNumOutputs)
{
activeOutputs--;
disposeBuffers();
return ASE_InvalidParameter;
}
}
}
if (notEnoughMem)
{
disposeBuffers();
return ASE_NoMemory;
}
this->callbacks = callbacks;
if (callbacks->asioMessage (kAsioSupportsTimeInfo, 0, 0, 0))
{
timeInfoMode = true;
asioTime.timeInfo.speed = 1.;
asioTime.timeInfo.systemTime.hi = asioTime.timeInfo.systemTime.lo = 0;
asioTime.timeInfo.samplePosition.hi = asioTime.timeInfo.samplePosition.lo = 0;
asioTime.timeInfo.sampleRate = sampleRate;
asioTime.timeInfo.flags = kSystemTimeValid | kSamplePositionValid | kSampleRateValid;
asioTime.timeCode.speed = 1.;
asioTime.timeCode.timeCodeSamples.lo = asioTime.timeCode.timeCodeSamples.hi = 0;
asioTime.timeCode.flags = kTcValid | kTcRunning ;
}
else
timeInfoMode = false;
return ASE_OK;
}
//---------------------------------------------------------------------------------------------
ASIOError AsioSample::disposeBuffers()
{
long i;
callbacks = 0;
stop();
for (i = 0; i < activeInputs; i++)
delete inputBuffers[i];
activeInputs = 0;
for (i = 0; i < activeOutputs; i++)
delete outputBuffers[i];
activeOutputs = 0;
return ASE_OK;
}
//---------------------------------------------------------------------------------------------
ASIOError AsioSample::controlPanel()
{
return ASE_NotPresent;
}
//---------------------------------------------------------------------------------------------
ASIOError AsioSample::future (long selector, void* opt) // !!! check properties
{
ASIOTransportParameters* tp = (ASIOTransportParameters*)opt;
switch (selector)
{
case kAsioEnableTimeCodeRead: tcRead = true; return ASE_SUCCESS;
case kAsioDisableTimeCodeRead: tcRead = false; return ASE_SUCCESS;
case kAsioSetInputMonitor: return ASE_SUCCESS; // for testing!!!
case kAsioCanInputMonitor: return ASE_SUCCESS; // for testing!!!
case kAsioCanTimeInfo: return ASE_SUCCESS;
case kAsioCanTimeCode: return ASE_SUCCESS;
}
return ASE_NotPresent;
}
//--------------------------------------------------------------------------------------------------------
// private methods
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
// input
//--------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
bool AsioSample::inputOpen ()
{
#if TESTWAVES
sineWave = new short[blockFrames];
if (!sineWave)
{
strcpy (errorMessage, "ASIO Sample Driver: Out of Memory!");
return false;
}
makeSine (sineWave);
sawTooth = new short[blockFrames];
if (!sawTooth)
{
strcpy(errorMessage, "ASIO Sample Driver: Out of Memory!");
return false;
}
makeSaw(sawTooth);
#endif
return true;
}
#if TESTWAVES
#include <math.h>
const double pi = 0.3141592654;
//---------------------------------------------------------------------------------------------
void AsioSample::makeSine (short *wave)
{
double frames = (double)blockFrames;
double i, f = (pi * 2.) / frames;
for (i = 0; i < frames; i++)
*wave++ = (short)((double)0x7fff * sin(f * i));
}
//---------------------------------------------------------------------------------------------
void AsioSample::makeSaw(short *wave)
{
double frames = (double)blockFrames;
double i, f = 2. / frames;
for (i = 0; i < frames; i++)
*wave++ = (short)((double)0x7fff * (-1. + f * i));
}
#endif
//---------------------------------------------------------------------------------------------
void AsioSample::inputClose ()
{
#if TESTWAVES
if (sineWave)
delete sineWave;
sineWave = 0;
if (sawTooth)
delete sawTooth;
sawTooth = 0;
#endif
}
//---------------------------------------------------------------------------------------------
void AsioSample::input()
{
#if TESTWAVES
long i;
short *in = 0;
for (i = 0; i < activeInputs; i++)
{
in = inputBuffers[i];
if (in)
{
if (toggle)
in += blockFrames;
if ((i & 1) && sawTooth)
memcpy(in, sawTooth, (unsigned long)(blockFrames * 2));
else if (sineWave)
memcpy(in, sineWave, (unsigned long)(blockFrames * 2));
}
}
#endif
}
//------------------------------------------------------------------------------------------------------------------
// output
//------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
bool AsioSample::outputOpen()
{
return true;
}
//---------------------------------------------------------------------------------------------
void AsioSample::outputClose ()
{
}
//---------------------------------------------------------------------------------------------
void AsioSample::output ()
{
}
//---------------------------------------------------------------------------------------------
void AsioSample::bufferSwitch ()
{
if (started && callbacks)
{
getNanoSeconds(&theSystemTime); // latch system time
input();
output();
samplePosition += blockFrames;
if (timeInfoMode)
bufferSwitchX ();
else
callbacks->bufferSwitch (toggle, ASIOFalse);
toggle = toggle ? 0 : 1;
}
}
//---------------------------------------------------------------------------------------------
// asio2 buffer switch
void AsioSample::bufferSwitchX ()
{
getSamplePosition (&asioTime.timeInfo.samplePosition, &asioTime.timeInfo.systemTime);
long offset = toggle ? blockFrames : 0;
if (tcRead)
{ // Create a fake time code, which is 10 minutes ahead of the card's sample position
// Please note that for simplicity here time code will wrap after 32 bit are reached
asioTime.timeCode.timeCodeSamples.lo = asioTime.timeInfo.samplePosition.lo + 600.0 * sampleRate;
asioTime.timeCode.timeCodeSamples.hi = 0;
}
callbacks->bufferSwitchTimeInfo (&asioTime, toggle, ASIOFalse);
asioTime.timeInfo.flags &= ~(kSampleRateChanged | kClockSourceChanged);
}
//---------------------------------------------------------------------------------------------
ASIOError AsioSample::outputReady ()
{
return ASE_NotPresent;
}
//---------------------------------------------------------------------------------------------
double AsioSamples2double (ASIOSamples* samples)
{
double a = (double)(samples->lo);
if (samples->hi)
a += (double)(samples->hi) * twoRaisedTo32;
return a;
}
+148
View File
@@ -0,0 +1,148 @@
/*
Steinberg Audio Stream I/O API
(c) 1999, Steinberg Soft- und Hardware GmbH
asiosmpl.h
test implementation of asio
*/
#ifndef _asiosmpl_
#define _asiosmpl_
#include "asiosys.h"
#define TESTWAVES 1
// when true, will feed the left input (to host) with
// a sine wave, and the right one with a sawtooth
enum
{
kBlockFrames = 256,
kNumInputs = 16,
kNumOutputs = 16
};
#if WINDOWS
#include "rpc.h"
#include "rpcndr.h"
#ifndef COM_NO_WINDOWS_H
#include <windows.h>
#include "ole2.h"
#endif
#include "combase.h"
#include "iasiodrv.h"
class AsioSample : public IASIO, public CUnknown
{
public:
AsioSample(LPUNKNOWN pUnk, HRESULT *phr);
~AsioSample();
DECLARE_IUNKNOWN
//STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \
// return GetOwner()->QueryInterface(riid,ppv); \
//}; \
//STDMETHODIMP_(ULONG) AddRef() { \
// return GetOwner()->AddRef(); \
//}; \
//STDMETHODIMP_(ULONG) Release() { \
// return GetOwner()->Release(); \
//};
// Factory method
static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
// IUnknown
virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);
#else
#include "asiodrvr.h"
//---------------------------------------------------------------------------------------------
class AsioSample : public AsioDriver
{
public:
AsioSample ();
~AsioSample ();
#endif
ASIOBool init (void* sysRef);
void getDriverName (char *name); // max 32 bytes incl. terminating zero
long getDriverVersion ();
void getErrorMessage (char *string); // max 128 bytes incl.
ASIOError start ();
ASIOError stop ();
ASIOError getChannels (long *numInputChannels, long *numOutputChannels);
ASIOError getLatencies (long *inputLatency, long *outputLatency);
ASIOError getBufferSize (long *minSize, long *maxSize,
long *preferredSize, long *granularity);
ASIOError canSampleRate (ASIOSampleRate sampleRate);
ASIOError getSampleRate (ASIOSampleRate *sampleRate);
ASIOError setSampleRate (ASIOSampleRate sampleRate);
ASIOError getClockSources (ASIOClockSource *clocks, long *numSources);
ASIOError setClockSource (long index);
ASIOError getSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);
ASIOError getChannelInfo (ASIOChannelInfo *info);
ASIOError createBuffers (ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks);
ASIOError disposeBuffers ();
ASIOError controlPanel ();
ASIOError future (long selector, void *opt);
ASIOError outputReady ();
void bufferSwitch ();
long getMilliSeconds () {return milliSeconds;}
private:
friend void myTimer();
bool inputOpen ();
#if TESTWAVES
void makeSine (short *wave);
void makeSaw (short *wave);
#endif
void inputClose ();
void input ();
bool outputOpen ();
void outputClose ();
void output ();
void timerOn ();
void timerOff ();
void bufferSwitchX ();
double samplePosition;
double sampleRate;
ASIOCallbacks *callbacks;
ASIOTime asioTime;
ASIOTimeStamp theSystemTime;
short *inputBuffers[kNumInputs * 2];
short *outputBuffers[kNumOutputs * 2];
#if TESTWAVES
short *sineWave, *sawTooth;
#endif
long inMap[kNumInputs];
long outMap[kNumOutputs];
long blockFrames;
long inputLatency;
long outputLatency;
long activeInputs;
long activeOutputs;
long toggle;
long milliSeconds;
bool active, started;
bool timeInfoMode, tcRead;
char errorMessage[128];
};
#endif
+15
View File
@@ -0,0 +1,15 @@
#include "asio.h"
#include <Timer.h>
void getNanoSeconds(ASIOTimeStamp *time);
static const double twoRaisedTo32 = 4294967296.;
void getNanoSeconds(ASIOTimeStamp *time)
{
UnsignedWide ys;
Microseconds(&ys);
double r = 1000. * ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
time->hi = (unsigned long)(r / twoRaisedTo32);
time->lo = (unsigned long)(r - (double)time->hi * twoRaisedTo32);
}
+53
View File
@@ -0,0 +1,53 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
charlie (May 1996)
asiosmpl.cpp
sample implementation of asio.
time manager irq
**** mac os specific ****
*/
#include <macheaders.h>
#include <Timer.h>
#include <string.h>
#include "asiosmpl.h"
static TMTask myTmTask;
static bool tmTaskOn = false;
static AsioSample *theSound = 0;
void myTimer();
void myTimer()
{
if(theSound)
theSound->bufferSwitch();
PrimeTime((QElemPtr)&myTmTask, theSound->milliSeconds);
+6
View File
@@ -0,0 +1,6 @@
#include "asiosmpl.h"
AsioDriver *getDriver()
{
return new AsioSample();
}
+55
View File
@@ -0,0 +1,55 @@
#include <windows.h>
#include "asiosmpl.h"
static DWORD __stdcall ASIOThread (void *param);
static HANDLE ASIOThreadHandle = 0;
static bool done = false;
const double twoRaisedTo32 = 4294967296.;
AsioSample* theDriver = 0;
//------------------------------------------------------------------------------------------
void getNanoSeconds (ASIOTimeStamp* ts)
{
double nanoSeconds = (double)((unsigned long)timeGetTime ()) * 1000000.;
ts->hi = (unsigned long)(nanoSeconds / twoRaisedTo32);
ts->lo = (unsigned long)(nanoSeconds - (ts->hi * twoRaisedTo32));
}
//------------------------------------------------------------------------------------------
void AsioSample::timerOn ()
{
theDriver = this;
DWORD asioId;
done = false;
ASIOThreadHandle = CreateThread (0, 0, &ASIOThread, 0, 0, &asioId);
}
//------------------------------------------------------------------------------------------
void AsioSample::timerOff ()
{
done = true;
if (ASIOThreadHandle)
WaitForSingleObject(ASIOThreadHandle, 1000);
ASIOThreadHandle = 0;
}
//------------------------------------------------------------------------------------------
static DWORD __stdcall ASIOThread (void *param)
{
do
{
if (theDriver)
{
theDriver->bufferSwitch ();
Sleep (theDriver->getMilliSeconds ());
}
else
{
double a = 1000. / 44100.;
Sleep ((long)(a * (double)kBlockFrames));
}
} while (!done);
return 0;
}
+859
View File
@@ -0,0 +1,859 @@
#include "ginclude.h"
#include "ASIOConvertSamples.h"
#include <math.h>
#if MAC
#define TRUNCATE 0
#elif ASIO_CPU_X86 || ASIO_CPU_SPARC || ASIO_CPU_MIPS
#define TRUNCATE 1
#undef MAXFLOAT
#define MAXFLOAT 0x7fffff00L
#endif
ASIOConvertSamples::ASIOConvertSamples()
{
}
//-------------------------------------------------------------------------------------------
// mono
void ASIOConvertSamples::convertMono8Unsigned(long *source, char *dest, long frames)
{
unsigned char *c = (unsigned char *)source;
unsigned char a;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = c[3];
#else
a = c[0];
#endif
c += 4;
a -= 0x80U;
*++dest = a;
}
}
void ASIOConvertSamples::convertMono8(long *source, char *dest, long frames)
{
char *c = (char *)source;
char a;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = c[3];
#else
a = c[0];
#endif
c += 4;
*++dest = a;
}
}
void ASIOConvertSamples::convertMono16(long *source, short *dest, long frames)
{
#if ASIO_LITTLE_ENDIAN
char* s = (char*)source;
char* d = (char*)dest;
while(--frames >= 0)
{
*d++ = s[3]; // dest big endian, msb first
*d++ = s[2];
s += 4;
}
#else
long l;
source--;
dest--;
while(--frames >= 0)
{
l = *++source;
*++dest = (short)(l >> 16);
}
#endif
}
void ASIOConvertSamples::convertMono24(long *source, char *dest, long frames)
{
// work with chars in order to prevent misalignments
char *s = (char *)source;
char a, b, c;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = s[3]; // msb
b = s[2];
c = s[1]; // lsb
#else
a = s[0];
b = s[1];
c = s[2];
#endif
s += 4;
*++dest = a; // big endian, msb first
*++dest = b;
*++dest = c;
}
}
// small endian
void ASIOConvertSamples::convertMono16SmallEndian(long *source, short *dest, long frames)
{
char *s = (char *)source;
char *d = (char *)dest;
char a, b;
d--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = s[3];
b = s[2];
#else
a = s[0];
b = s[1];
#endif
s += 4;
*++d = b; // dest small endian, lsb first
*++d = a;
}
}
void ASIOConvertSamples::convertMono24SmallEndian(long *source, char *dest, long frames)
{
// work with chars in order to prevent misalignments
char *s = (char *)source;
char a, b, c;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = s[3];
b = s[2];
c = s[1];
#else
a = s[0];
b = s[1];
c = s[2];
#endif
s += 4;
*++dest = c; // lsb first
*++dest = b;
*++dest = a;
}
}
//-------------------------------------------------------------------------------------------
// stereo interleaved
void ASIOConvertSamples::convertStereo8InterleavedUnsigned(long *left, long *right, char *dest, long frames)
{
unsigned char *cl = (unsigned char *)left;
unsigned char *cr = (unsigned char *)right;
unsigned char a, b;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = cl[3];
b = cr[3];
#else
a = cl[0];
b = cr[0];
#endif
cl += 4;
cr += 4;
a -= 0x80U;
b -= 0x80U;
*++dest = a;
*++dest = b;
}
}
void ASIOConvertSamples::convertStereo8Interleaved(long *left, long *right, char *dest, long frames)
{
unsigned char *cl = (unsigned char *)left;
unsigned char *cr = (unsigned char *)right;
unsigned char a, b;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = cl[3];
b = cr[3];
#else
a = cl[0];
b = cr[0];
#endif
cl += 4;
cr += 4;
*++dest = a;
*++dest = b;
}
}
void ASIOConvertSamples::convertStereo16Interleaved(long *left, long *right, short *dest, long frames)
{
#if ASIO_LITTLE_ENDIAN
char* sl = (char*)left;
char* sr = (char*)right;
char* d = (char*)dest;
while(--frames >= 0)
{
*d++ = sl[3]; // msb first
*d++ = sl[2];
*d++ = sr[3];
*d++ = sr[2];
sl += 4;
sr += 4;
}
#else
long l, r;
left--;
right--;
dest--;
while(--frames >= 0)
{
l = *++left;
r = *++right;
*++dest = (short)(l >> 16);
*++dest = (short)(r >> 16);
}
#endif
}
void ASIOConvertSamples::convertStereo24Interleaved(long *left, long *right, char *dest, long frames)
{
// work with chars in order to prevent misalignments
char *sl = (char *)left;
char *sr = (char *)right;
char al, bl, cl, ar, br, cr;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
al = sl[3];
bl = sl[2];
cl = sl[1];
ar = sr[3];
br = sr[2];
cr = sr[1];
#else
al = sl[0];
bl = sl[1];
cl = sl[2];
ar = sr[0];
br = sr[1];
cr = sr[2];
#endif
sl += 4;
sr += 4;
*++dest = al;
*++dest = bl;
*++dest = cl;
*++dest = ar;
*++dest = br;
*++dest = cr;
}
}
void ASIOConvertSamples::convertStereo16InterleavedSmallEndian(long *left, long *right, short *dest, long frames)
{
char *sl = (char *)left;
char *sr = (char *)right;
char *d = (char *)dest;
char al, bl, ar, br;
d--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
al = sl[3];
bl = sl[2];
ar = sr[3];
br = sr[2];
#else
al = sl[0];
bl = sl[1];
ar = sr[0];
br = sr[1];
#endif
sl += 4;
sr += 4;
*++d = bl; // lsb first
*++d = al;
*++d = br;
*++d = ar;
}
}
void ASIOConvertSamples::convertStereo24InterleavedSmallEndian(long *left, long *right, char *dest, long frames)
{
// work with chars in order to prevent misalignments
char *sl = (char *)left;
char *sr = (char *)right;
char al, bl, cl, ar, br, cr;
dest--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
al = sl[3];
bl = sl[2];
cl = sl[1];
ar = sr[3];
br = sr[2];
cr = sr[1];
#else
al = sl[0];
bl = sl[1];
cl = sl[2];
ar = sr[0];
br = sr[1];
cr = sr[2];
#endif
sl += 4;
sr += 4;
*++dest = cl;
*++dest = bl;
*++dest = al;
*++dest = cr;
*++dest = br;
*++dest = ar;
}
}
//-------------------------------------------------------------------------------------------
// stereo split
void ASIOConvertSamples::convertStereo8Unsigned(long *left, long *right, char *dLeft, char *dRight, long frames)
{
unsigned char *cl = (unsigned char *)left;
unsigned char *cr = (unsigned char *)right;
unsigned char a, b;
dLeft--;
dRight--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = cl[3];
b = cr[3];
#else
a = cl[0];
b = cr[0];
#endif
cl += 4;
cr += 4;
a -= 0x80U;
b -= 0x80U;
*++dLeft = a;
*++dRight = b;
}
}
void ASIOConvertSamples::convertStereo8(long *left, long *right, char *dLeft, char *dRight, long frames)
{
unsigned char *cl = (unsigned char *)left;
unsigned char *cr = (unsigned char *)right;
unsigned char a, b;
dLeft--;
dRight--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = cl[3];
b = cr[3];
#else
a = cl[0];
b = cr[0];
#endif
cl += 4;
cr += 4;
*++dLeft = a;
*++dRight = b;
}
}
void ASIOConvertSamples::convertStereo16(long *left, long *right, short *dLeft, short *dRight, long frames)
{
#if ASIO_LITTLE_ENDIAN
char* sl = (char*)left;
char* sr = (char*)right;
char* dl = (char*)dLeft;
char* dr = (char*)dRight;
while(--frames >= 0)
{
*dl++ = sl[3]; // msb first
*dl++ = sl[2];
*dr++ = sr[3];
*dr++ = sr[2];
sl += 4;
sr += 4;
}
#else
long l, r;
left--;
right--;
dLeft--;
dRight--;
while(--frames >= 0)
{
l = *++left;
r = *++right;
*++dLeft = (short)(l >> 16);
*++dRight = (short)(r >> 16);
}
#endif
}
void ASIOConvertSamples::convertStereo24(long *left, long *right, char *dLeft, char *dRight, long frames)
{
// work with chars in order to prevent misalignments
char *sl = (char *)left;
char *sr = (char *)right;
char al, bl, cl, ar, br, cr;
dLeft--;
dRight--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
al = sl[3];
bl = sl[2];
cl = sl[1];
ar = sr[3];
br = sr[2];
cr = sr[1];
#else
al = sl[0];
bl = sl[1];
cl = sl[2];
ar = sr[0];
br = sr[1];
cr = sr[2];
#endif
sl += 4;
sr += 4;
*++dLeft = al;
*++dLeft = bl;
*++dLeft = cl;
*++dRight = ar;
*++dRight = br;
*++dRight = cr;
}
}
// small endian
void ASIOConvertSamples::convertStereo16SmallEndian(long *left, long *right, short *dLeft, short *dRight, long frames)
{
char *sl = (char *)left;
char *sr = (char *)right;
char *dl = (char *)dLeft;
char *dr = (char *)dRight;
char al, bl, ar, br;
dl--;
dr--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
al = sl[3];
bl = sl[2];
ar = sr[3];
br = sr[2];
#else
al = sl[0];
bl = sl[1];
ar = sr[0];
br = sr[1];
#endif
sl += 4;
sr += 4;
*++dl = bl;
*++dl = al;
*++dr = br;
*++dr = ar;
}
}
void ASIOConvertSamples::convertStereo24SmallEndian(long *left, long *right, char *dLeft, char *dRight, long frames)
{
// work with chars in order to prevent misalignments
char *sl = (char *)left;
char *sr = (char *)right;
char al, bl, cl, ar, br, cr;
dLeft--;
dRight--;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
al = sl[3];
bl = sl[2];
cl = sl[1];
ar = sr[3];
br = sr[2];
cr = sr[1];
#else
al = sl[0];
bl = sl[1];
cl = sl[2];
ar = sr[0];
br = sr[1];
cr = sr[2];
#endif
sl += 4;
sr += 4;
*++dLeft = cl;
*++dLeft = bl;
*++dLeft = al;
*++dRight = cr;
*++dRight = br;
*++dRight = ar;
}
}
//------------------------------------------------------------------------------------------
// in place integer conversions
void ASIOConvertSamples::int32msb16to16inPlace(long *in, long frames)
{
short *d1 = (short *)in;
short* out = d1;
#if ASIO_LITTLE_ENDIAN
d1++;
#endif
while(--frames >= 0)
{
*out++ = *d1;
d1 += 2;
}
}
void ASIOConvertSamples::int32lsb16to16inPlace(long *in, long frames)
{
short *d1 = (short *)in;
short* out = d1;
#if !ASIO_LITTLE_ENDIAN
d1++;
#endif
while(--frames >= 0)
{
*out++ = *d1;
d1 += 2;
}
}
void ASIOConvertSamples::int32msb16shiftedTo16inPlace(long *in, long frames, long shift)
{
short* out = (short*)in;
while(--frames >= 0)
*out++ = (short)(*in++ >> shift);
}
void ASIOConvertSamples::int24msbto16inPlace(unsigned char *in, long frames)
{
short a;
short* out = (short*)in;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = (short)in[2];
a <<= 8;
a |= (in[1] & 0xff);
#else
a = (short)in[0];
a <<= 8;
a |= (in[1] & 0xff);
#endif
*out++ = a;
in += 3;
}
}
//-----------------------------------------------------------------------------------------
void ASIOConvertSamples::shift32(void* buffer, long shiftAmount, long targetByteWidth,
bool revertEndian, long sampleFrames)
{
long a;
long frames = sampleFrames;
long* source = (long*)buffer;
if(revertEndian)
{
reverseEndian(buffer, 4, sampleFrames);
revertEndian = false;
}
if(targetByteWidth == 2)
{
short* dest = (short*)buffer;
short* al = (short*)&a;
#if ASIO_LITTLE_ENDIAN
al++;
#endif
while(--frames >= 0)
{
a = *source++;
a <<= shiftAmount;
*dest++ = *al;
}
}
else if(targetByteWidth == 3)
{
char* dest = (char*)buffer;
long* source = (long*)buffer;
char* aa = (char*)&a;
while(--frames >= 0)
{
a = *source++;
a <<= shiftAmount;
#if ASIO_LITTLE_ENDIAN
dest[0] = aa[1]; // lsb
dest[1] = aa[2];
dest[2] = aa[3]; // msb
#else
dest[0] = aa[0]; // msb
dest[1] = aa[1];
dest[2] = aa[2]; // lsb
#endif
dest += 3;
}
}
else if(targetByteWidth == 4)
{
long* dest = source;
while(--frames >= 0)
*dest++ = *source++ << shiftAmount;
}
}
void ASIOConvertSamples::reverseEndian(void* buffer, long byteWidth, long frames)
{
char* a = (char*)buffer;
char* b = a;
char c;
if(byteWidth == 2)
{
while(--frames >= 0)
{
c = a[0];
a[0] = a[1];
a[1] = c;
a += 2;
}
}
else if(byteWidth == 3)
{
while(--frames >= 0)
{
c = a[0];
a[0] = a[2];
a[2] = c;
a += 3;
}
}
else if(byteWidth == 4)
{
while(--frames >= 0)
{
c = a[0];
a[0] = a[3];
a[3] = c;
c = a[1];
a[1] = a[2];
a[2] = c;
a += 4;
}
}
}
//-------------------------------------------------------------------------------------------------
void ASIOConvertSamples::int32to16inPlace(void* buffer, long frames)
{
short* in = (short*)buffer;
short* out = in;
#if ASIO_LITTLE_ENDIAN
in++;
#endif
while(--frames >= 0)
{
*out++ = *in;
in += 2;
}
}
void ASIOConvertSamples::int24to16inPlace(void* buffer, long frames)
{
char* from = (char*)buffer;
char* to = from;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
to[0] = from[1];
to[1] = from[2];
#else
to[0] = from[0];
to[1] = from[1];
#endif
from += 3;
to += 2;
}
}
void ASIOConvertSamples::int32to24inPlace(void* buffer, long frames)
{
long* in = (long*)buffer;
char* out = (char*)buffer;
long a;
while(--frames >= 0)
{
a = *in++;
a >>= 8; // 32->24
#if ASIO_LITTLE_ENDIAN
out[0] = (char)a; // lsb
a >>= 8;
out[1] = (char)a;
a >>= 8;
out[2] = (char)a;
#else
out[2] = (char)a; // lsb
a >>= 8;
out[1] = (char)a;
a >>= 8;
out[0] = (char)a;
#endif
out += 3;
}
}
void ASIOConvertSamples::int16to24inPlace(void* buffer, long frames)
{
char* in = (char*)buffer;
char* out = (char*)buffer;
in += frames * 2;
out += frames * 3;
while(--frames >= 0)
{
out -= 3;
in -= 2;
#if ASIO_LITTLE_ENDIAN
out[2] = in[1]; // msb
out[1] = in[0]; // lsb
out[0] = 0;
#else
out[2] = 0;
out[1] = in[1]; // lsb
out[0] = in[0]; // msb
#endif
}
}
void ASIOConvertSamples::int24to32inPlace(void* buffer, long frames)
{
long a, b, c;
char* in = (char*)buffer;
long* out = (long*)buffer;
in += (frames * 3);
out += frames;
while(--frames >= 0)
{
#if ASIO_LITTLE_ENDIAN
a = (long)in[-1]; // msb
b = (long)in[-2];
c = (long)in[-3];
#else
a = (long)in[-3]; // msb
b = (long)in[-2];
c = (long)in[-1];
#endif
a <<= 24;
b <<= 16;
b &= 0x00ff0000;
a |= b;
c <<= 8;
c &= 0x0000ff00;
a |= c;
*--out = a;
in -= 3;
}
}
void ASIOConvertSamples::int16to32inPlace(void* buffer, long frames)
{
short* in = (short*)buffer;
long* out = (long*)buffer;
in += frames;
out += frames;
while(--frames >= 0)
*--out = ((long)(*--in)) << 16;
}
//------------------------------------------------------------------------------------------
// float to int
const double fScaler16 = (double)0x7fffL;
const double fScaler24 = (double)0x7fffffL;
const double fScaler32 = (double)0x7fffffffL;
void ASIOConvertSamples::float32toInt16inPlace(float* buffer, long frames)
{
double sc = fScaler16 + .49999;
short* b = (short*)buffer;
while(--frames >= 0)
*b++ = (short)((double)(*buffer++) * sc);
}
void ASIOConvertSamples::float32toInt24inPlace(float* buffer, long frames)
{
double sc = fScaler24 + .49999;
long a;
char* b = (char*)buffer;
char* aa = (char*)&a;
while(--frames >= 0)
{
a = (long)((double)(*buffer++) * sc);
#if ASIO_LITTLE_ENDIAN
*b++ = aa[3];
*b++ = aa[2];
*b++ = aa[1];
#else
*b++ = aa[1];
*b++ = aa[2];
*b++ = aa[3];
#endif
}
}
void ASIOConvertSamples::float32toInt32inPlace(float* buffer, long frames)
{
double sc = fScaler32 + .49999;
long* b = (long*)buffer;
while(--frames >= 0)
*b++ = (long)((double)(*buffer++) * sc);
}
+62
View File
@@ -0,0 +1,62 @@
#ifndef __ASIOConvertSamples__
#define __ASIOConvertSamples__
class ASIOConvertSamples
{
public:
ASIOConvertSamples();
~ASIOConvertSamples() {}
// format converters, input 32 bit integer
// mono
void convertMono8(long *source, char *dest, long frames);
void convertMono8Unsigned(long *source, char *dest, long frames);
void convertMono16(long *source, short *dest, long frames);
void convertMono16SmallEndian(long *source, short *dest, long frames);
void convertMono24(long *source, char *dest, long frames);
void convertMono24SmallEndian(long *source, char *dest, long frames);
// stereo interleaved
void convertStereo8Interleaved(long *left, long *right, char *dest, long frames);
void convertStereo8InterleavedUnsigned(long *left, long *right, char *dest, long frames);
void convertStereo16Interleaved(long *left, long *right, short *dest, long frames);
void convertStereo16InterleavedSmallEndian(long *left, long *right, short *dest, long frames);
void convertStereo24Interleaved(long *left, long *right, char *dest, long frames);
void convertStereo24InterleavedSmallEndian(long *left, long *right, char *dest, long frames);
// stereo split
void convertStereo8(long *left, long *right, char *dLeft, char *dRight, long frames);
void convertStereo8Unsigned(long *left, long *right, char *dLeft, char *dRight, long frames);
void convertStereo16(long *left, long *right, short *dLeft, short *dRight, long frames);
void convertStereo16SmallEndian(long *left, long *right, short *dLeft, short *dRight, long frames);
void convertStereo24(long *left, long *right, char *dLeft, char *dRight, long frames);
void convertStereo24SmallEndian(long *left, long *right, char *dLeft, char *dRight, long frames);
// integer in place conversions
void int32msb16to16inPlace(long *in, long frames);
void int32lsb16to16inPlace(long *in, long frames);
void int32msb16shiftedTo16inPlace(long *in1, long frames, long shift);
void int24msbto16inPlace(unsigned char *in, long frames);
// integer to integer
void shift32(void* buffer, long shiftAmount, long targetByteWidth,
bool reverseEndian, long frames);
void reverseEndian(void* buffer, long byteWidth, long frames);
void int32to16inPlace(void* buffer, long frames);
void int24to16inPlace(void* buffer, long frames);
void int32to24inPlace(void* buffer, long frames);
void int16to24inPlace(void* buffer, long frames);
void int24to32inPlace(void* buffer, long frames);
void int16to32inPlace(void* buffer, long frames);
// float to integer
void float32toInt16inPlace(float* buffer, long frames);
void float32toInt24inPlace(float* buffer, long frames);
void float32toInt32inPlace(float* buffer, long frames);
};
#endif
+186
View File
@@ -0,0 +1,186 @@
#include <string.h>
#include "asiodrivers.h"
AsioDrivers* asioDrivers = 0;
bool loadAsioDriver(char *name);
bool loadAsioDriver(char *name)
{
if(!asioDrivers)
asioDrivers = new AsioDrivers();
if(asioDrivers)
return asioDrivers->loadDriver(name);
return false;
}
//------------------------------------------------------------------------------------
#if MAC
bool resolveASIO(unsigned long aconnID);
AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio')
{
connID = -1;
curIndex = -1;
}
AsioDrivers::~AsioDrivers()
{
removeCurrentDriver();
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
if(curIndex >= 0)
return getName(curIndex, name);
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
for(long i = 0; i < getNumFragments() && i < maxDrivers; i++)
getName(i, names[i]);
return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers;
}
bool AsioDrivers::loadDriver(char *name)
{
char dname[64];
unsigned long newID;
for(long i = 0; i < getNumFragments(); i++)
{
if(getName(i, dname) && !strcmp(name, dname))
{
if(newInstance(i, &newID))
{
if(resolveASIO(newID))
{
if(connID != -1)
removeInstance(curIndex, connID);
curIndex = i;
connID = newID;
return true;
}
}
break;
}
}
return false;
}
void AsioDrivers::removeCurrentDriver()
{
if(connID != -1)
removeInstance(curIndex, connID);
connID = -1;
curIndex = -1;
}
//------------------------------------------------------------------------------------
#elif WINDOWS
#include "iasiodrv.h"
extern IASIO* theAsioDriver;
AsioDrivers::AsioDrivers() : AsioDriverList()
{
curIndex = -1;
}
AsioDrivers::~AsioDrivers()
{
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
if(curIndex >= 0)
return asioGetDriverName(curIndex, name, 32) == 0 ? true : false;
name[0] = 0;
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++)
asioGetDriverName(i, names[i], 32);
return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers;
}
bool AsioDrivers::loadDriver(char *name)
{
char dname[64];
char curName[64];
for(long i = 0; i < asioGetNumDev(); i++)
{
if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname))
{
curName[0] = 0;
getCurrentDriverName(curName); // in case we fail...
removeCurrentDriver();
if(!asioOpenDriver(i, (void **)&theAsioDriver))
{
curIndex = i;
return true;
}
else
{
theAsioDriver = 0;
if(curName[0] && strcmp(dname, curName))
loadDriver(curName); // try restore
}
break;
}
}
return false;
}
void AsioDrivers::removeCurrentDriver()
{
if(curIndex != -1)
asioCloseDriver(curIndex);
curIndex = -1;
}
#elif SGI || BEOS
#include "asiolist.h"
AsioDrivers::AsioDrivers()
: AsioDriverList()
{
curIndex = -1;
}
AsioDrivers::~AsioDrivers()
{
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
return 0;
}
bool AsioDrivers::loadDriver(char *name)
{
return false;
}
void AsioDrivers::removeCurrentDriver()
{
}
#else
#error implement me
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef __AsioDrivers__
#define __AsioDrivers__
#include "ginclude.h"
#if MAC
#include "CodeFragments.hpp"
class AsioDrivers : public CodeFragments
#elif WINDOWS
#include <windows.h>
#include "asiolist.h"
class AsioDrivers : public AsioDriverList
#elif SGI || BEOS
#include "asiolist.h"
class AsioDrivers : public AsioDriverList
#else
#error implement me
#endif
{
public:
AsioDrivers();
~AsioDrivers();
bool getCurrentDriverName(char *name);
long getDriverNames(char **names, long maxDrivers);
bool loadDriver(char *name);
void removeCurrentDriver();
long getCurrentDriverIndex() {return curIndex;}
protected:
unsigned long connID;
long curIndex;
};
#endif
+38
View File
@@ -0,0 +1,38 @@
#ifndef __gInclude__
#define __gInclude__
#if SGI
#undef BEOS
#undef MAC
#undef WINDOWS
//
#define ASIO_BIG_ENDIAN 1
#define ASIO_CPU_MIPS 1
#elif defined WIN32
#undef BEOS
#undef MAC
#undef SGI
#define WINDOWS 1
#define ASIO_LITTLE_ENDIAN 1
#define ASIO_CPU_X86 1
#elif BEOS
#undef MAC
#undef SGI
#undef WINDOWS
#define ASIO_LITTLE_ENDIAN 1
#define ASIO_CPU_X86 1
//
#else
#define MAC 1
#undef BEOS
#undef WINDOWS
#undef SGI
#define ASIO_BIG_ENDIAN 1
#define ASIO_CPU_PPC 1
#endif
// always
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#endif // __gInclude__
+1
View File
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
#ifndef __CodeFragments__
+268
View File
@@ -0,0 +1,268 @@
#include <windows.h>
#include "iasiodrv.h"
#include "asiolist.h"
#define ASIODRV_DESC "description"
#define INPROC_SERVER "InprocServer32"
#define ASIO_PATH "software\\asio"
#define COM_CLSID "clsid"
// ******************************************************************
// Local Functions
// ******************************************************************
static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
{
HKEY hkEnum,hksub,hkpath;
char databuf[512];
LONG cr,rc = -1;
DWORD datatype,datasize;
DWORD index;
OFSTRUCT ofs;
HFILE hfile;
BOOL found = FALSE;
CharLowerBuffA(clsidstr,strlen(clsidstr));
if ((cr = RegOpenKeyA(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
index = 0;
while (cr == ERROR_SUCCESS && !found) {
cr = RegEnumKeyA(hkEnum,index++,(LPSTR)databuf,512);
if (cr == ERROR_SUCCESS) {
CharLowerBuffA(databuf,strlen(databuf));
if (!(strcmp(databuf,clsidstr))) {
if ((cr = RegOpenKeyExA(hkEnum,(LPCSTR)databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
if ((cr = RegOpenKeyExA(hksub,(LPCSTR)INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
datatype = REG_SZ; datasize = (DWORD)dllpathsize;
cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
if (cr == ERROR_SUCCESS) {
memset(&ofs,0,sizeof(OFSTRUCT));
ofs.cBytes = sizeof(OFSTRUCT);
hfile = OpenFile(dllpath,&ofs,OF_EXIST);
if (hfile) rc = 0;
}
RegCloseKey(hkpath);
}
RegCloseKey(hksub);
}
found = TRUE; // break out
}
}
}
RegCloseKey(hkEnum);
}
return rc;
}
static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
{
HKEY hksub;
char databuf[256];
char dllpath[MAXPATHLEN];
WORD wData[100];
CLSID clsid;
DWORD datatype,datasize;
LONG cr,rc;
if (!lpdrv) {
if ((cr = RegOpenKeyExA(hkey,(LPCSTR)keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
datatype = REG_SZ; datasize = 256;
cr = RegQueryValueExA(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
if (cr == ERROR_SUCCESS) {
rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
if (rc == 0) {
lpdrv = new ASIODRVSTRUCT[1];
if (lpdrv) {
memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
lpdrv->drvID = drvID;
MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
}
datatype = REG_SZ; datasize = 256;
cr = RegQueryValueExA(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
if (cr == ERROR_SUCCESS) {
strcpy(lpdrv->drvname,databuf);
}
else strcpy(lpdrv->drvname,keyname);
}
}
}
RegCloseKey(hksub);
}
}
else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
return lpdrv;
}
static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
{
IASIO *iasio;
if (lpdrv != 0) {
deleteDrvStruct(lpdrv->next);
if (lpdrv->asiodrv) {
iasio = (IASIO *)lpdrv->asiodrv;
iasio->Release();
}
delete lpdrv;
}
}
static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
{
while (lpdrv) {
if (lpdrv->drvID == drvID) return lpdrv;
lpdrv = lpdrv->next;
}
return 0;
}
// ******************************************************************
// ******************************************************************
// AsioDriverList
// ******************************************************************
AsioDriverList::AsioDriverList ()
{
HKEY hkEnum = 0;
char keyname[MAXDRVNAMELEN];
LPASIODRVSTRUCT pdl;
LONG cr;
DWORD index = 0;
BOOL fin = FALSE;
numdrv = 0;
lpdrvlist = 0;
cr = RegOpenKeyA(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
while (cr == ERROR_SUCCESS) {
if ((cr = RegEnumKeyA(hkEnum,index++,(LPSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
}
else fin = TRUE;
}
if (hkEnum) RegCloseKey(hkEnum);
pdl = lpdrvlist;
while (pdl) {
numdrv++;
pdl = pdl->next;
}
if (numdrv) CoInitialize(0); // initialize COM
}
AsioDriverList::~AsioDriverList ()
{
if (numdrv) {
deleteDrvStruct(lpdrvlist);
CoUninitialize();
}
}
LONG AsioDriverList::asioGetNumDev (VOID)
{
return (LONG)numdrv;
}
LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
{
LPASIODRVSTRUCT lpdrv = 0;
long rc;
if (!asiodrv) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (!lpdrv->asiodrv) {
rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
if (rc == S_OK) {
lpdrv->asiodrv = *asiodrv;
return 0;
}
// else if (rc == REGDB_E_CLASSNOTREG)
// strcpy (info->messageText, "Driver not registered in the Registration Database!");
}
else rc = DRVERR_DEVICE_ALREADY_OPEN;
}
else rc = DRVERR_DEVICE_NOT_FOUND;
return rc;
}
LONG AsioDriverList::asioCloseDriver (int drvID)
{
LPASIODRVSTRUCT lpdrv = 0;
IASIO *iasio;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (lpdrv->asiodrv) {
iasio = (IASIO *)lpdrv->asiodrv;
iasio->Release();
lpdrv->asiodrv = 0;
}
}
return 0;
}
LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!drvname) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
strcpy(drvname,lpdrv->drvname);
}
else {
memcpy(drvname,lpdrv->drvname,drvnamesize-4);
drvname[drvnamesize-4] = '.';
drvname[drvnamesize-3] = '.';
drvname[drvnamesize-2] = '.';
drvname[drvnamesize-1] = 0;
}
return 0;
}
return DRVERR_DEVICE_NOT_FOUND;
}
LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!dllpath) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
strcpy(dllpath,lpdrv->dllpath);
return 0;
}
dllpath[0] = 0;
return DRVERR_INVALID_PARAM;
}
return DRVERR_DEVICE_NOT_FOUND;
}
LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!clsid) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
return 0;
}
return DRVERR_DEVICE_NOT_FOUND;
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef __asiolist__
#define __asiolist__
#define DRVERR -5000
#define DRVERR_INVALID_PARAM DRVERR-1
#define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2
#define DRVERR_DEVICE_NOT_FOUND DRVERR-3
#define MAXPATHLEN 512
#define MAXDRVNAMELEN 128
struct asiodrvstruct
{
int drvID;
CLSID clsid;
char dllpath[MAXPATHLEN];
char drvname[MAXDRVNAMELEN];
LPVOID asiodrv;
struct asiodrvstruct *next;
};
typedef struct asiodrvstruct ASIODRVSTRUCT;
typedef ASIODRVSTRUCT *LPASIODRVSTRUCT;
class AsioDriverList {
public:
AsioDriverList();
~AsioDriverList();
LONG asioOpenDriver (int,VOID **);
LONG asioCloseDriver (int);
// nice to have
LONG asioGetNumDev (VOID);
LONG asioGetDriverName (int,char *,int);
LONG asioGetDriverPath (int,char *,int);
LONG asioGetDriverCLSID (int,CLSID *);
// or use directly access
LPASIODRVSTRUCT lpdrvlist;
int numdrv;
};
typedef class AsioDriverList *LPASIODRIVERLIST;
#endif
BIN
View File
Binary file not shown.
View File
BIN
View File
Binary file not shown.
View File
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
View File
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+526
View File
@@ -0,0 +1,526 @@
// hostsample.cpp : a simple ASIO host example.
// - instantiates the driver
// - get the information from the driver
// - built up some audio channels
// - plays silence for 20 seconds
// - destruct the driver
// Note: This sample cannot work with the "ASIO DirectX Driver" as it does
// not have a valid Application Window handle, which is used as sysRef
// on the Windows platform.
#include <stdio.h>
#include <string.h>
#include "asiosys.h"
#include "asio.h"
#include "asiodrivers.h"
// name of the ASIO device to be used
#if WINDOWS
// #define ASIO_DRIVER_NAME "ASIO Multimedia Driver"
#define ASIO_DRIVER_NAME "ASIO Sample"
#elif MAC
// #define ASIO_DRIVER_NAME "Apple Sound Manager"
#define ASIO_DRIVER_NAME "ASIO Sample"
#endif
#define TEST_RUN_TIME 20.0 // run for 20 seconds
enum {
// number of input and outputs supported by the host application
// you can change these to higher or lower values
kMaxInputChannels = 32,
kMaxOutputChannels = 32
};
// internal data storage
typedef struct DriverInfo
{
// ASIOInit()
ASIODriverInfo driverInfo;
// ASIOGetChannels()
long inputChannels;
long outputChannels;
// ASIOGetBufferSize()
long minSize;
long maxSize;
long preferredSize;
long granularity;
// ASIOGetSampleRate()
ASIOSampleRate sampleRate;
// ASIOOutputReady()
bool postOutput;
// ASIOGetLatencies ()
long inputLatency;
long outputLatency;
// ASIOCreateBuffers ()
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
// ASIOGetChannelInfo()
ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
// The above two arrays share the same indexing, as the data in them are linked together
// Information from ASIOGetSamplePosition()
// data is converted to double floats for easier use, however 64 bit integer can be used, too
double nanoSeconds;
double samples;
double tcSamples; // time code samples
// bufferSwitchTimeInfo()
ASIOTime tInfo; // time info state
unsigned long sysRefTime; // system reference time, when bufferSwitch() was called
// Signal the end of processing in this example
bool stopped;
} DriverInfo;
DriverInfo asioDriverInfo = {0};
ASIOCallbacks asioCallbacks;
//----------------------------------------------------------------------------------
// some external references
extern AsioDrivers* asioDrivers;
bool loadAsioDriver(char *name);
// internal prototypes (required for the Metrowerks CodeWarrior compiler)
int main(int argc, char* argv[]);
long init_asio_static_data (DriverInfo *asioDriverInfo);
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo);
unsigned long get_sys_reference_time();
// callback prototypes
void bufferSwitch(long index, ASIOBool processNow);
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow);
void sampleRateChanged(ASIOSampleRate sRate);
long asioMessages(long selector, long value, void* message, double* opt);
//----------------------------------------------------------------------------------
long init_asio_static_data (DriverInfo *asioDriverInfo)
{ // collect the informational data of the driver
// get the number of available channels
if(ASIOGetChannels(&asioDriverInfo->inputChannels, &asioDriverInfo->outputChannels) == ASE_OK)
{
printf ("ASIOGetChannels (inputs: %d, outputs: %d);\n", asioDriverInfo->inputChannels, asioDriverInfo->outputChannels);
// get the usable buffer sizes
if(ASIOGetBufferSize(&asioDriverInfo->minSize, &asioDriverInfo->maxSize, &asioDriverInfo->preferredSize, &asioDriverInfo->granularity) == ASE_OK)
{
printf ("ASIOGetBufferSize (min: %d, max: %d, preferred: %d, granularity: %d);\n",
asioDriverInfo->minSize, asioDriverInfo->maxSize,
asioDriverInfo->preferredSize, asioDriverInfo->granularity);
// get the currently selected sample rate
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
{
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
if (asioDriverInfo->sampleRate <= 0.0 || asioDriverInfo->sampleRate > 96000.0)
{
// Driver does not store it's internal sample rate, so set it to a know one.
// Usually you should check beforehand, that the selected sample rate is valid
// with ASIOCanSampleRate().
if(ASIOSetSampleRate(44100.0) == ASE_OK)
{
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
else
return -6;
}
else
return -5;
}
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
if(ASIOOutputReady() == ASE_OK)
asioDriverInfo->postOutput = true;
else
asioDriverInfo->postOutput = false;
printf ("ASIOOutputReady(); - %s\n", asioDriverInfo->postOutput ? "Supported" : "Not supported");
return 0;
}
return -3;
}
return -2;
}
return -1;
}
//----------------------------------------------------------------------------------
// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
#if NATIVE_INT64
#define ASIO64toDouble(a) (a)
#else
const double twoRaisedTo32 = 4294967296.;
#define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
#endif
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. This is omitted here for simplicity.
static processedSamples = 0;
// store the timeInfo for later use
asioDriverInfo.tInfo = *timeInfo;
// 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);
else
asioDriverInfo.nanoSeconds = 0;
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);
else
asioDriverInfo.tcSamples = 0;
// get the system reference time
asioDriverInfo.sysRefTime = get_sys_reference_time();
#if WINDOWS && _DEBUG
// a few debug messages for the Windows device driver developer
// tells you the time when driver got its interrupt and the delay until the app receives
// the event notification.
static double last_samples = 0;
char tmp[128];
sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples));
OutputDebugString (tmp);
last_samples = asioDriverInfo.samples;
#endif
// buffer size in samples
long buffSize = asioDriverInfo.preferredSize;
// perform the processing
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
if (asioDriverInfo.bufferInfos[i].isInput == false)
{
// OK do processing for the outputs only
switch (asioDriverInfo.channelInfos[i].type)
{
case ASIOSTInt16LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24LSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
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
case ASIOSTInt32LSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTInt16MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24MSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
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
case ASIOSTInt32MSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
}
}
}
// finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
if (asioDriverInfo.postOutput)
ASIOOutputReady();
if (processedSamples >= asioDriverInfo.sampleRate * TEST_RUN_TIME) // roughly measured
asioDriverInfo.stopped = true;
else
processedSamples += buffSize;
return 0L;
}
//----------------------------------------------------------------------------------
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.
// as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs 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));
// 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)
timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
bufferSwitchTimeInfo (&timeInfo, index, processNow);
}
//----------------------------------------------------------------------------------
void sampleRateChanged(ASIOSampleRate sRate)
{
// 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
// might not have even changed, maybe only the sample rate status of an
// AES/EBU or S/PDIF digital input at the audio device.
// You might have to update time/sample related conversion routines, etc.
}
//----------------------------------------------------------------------------------
long asioMessages(long selector, long value, void* message, double* opt)
{
// currently the parameters "value", "message" and "opt" are not used.
long ret = 0;
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
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:
// 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;
}
//----------------------------------------------------------------------------------
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo)
{ // create buffers for all inputs and outputs of the card with the
// preferredSize from ASIOGetBufferSize() as buffer size
long i;
ASIOError result;
// fill the bufferInfos from the start without a gap
ASIOBufferInfo *info = asioDriverInfo->bufferInfos;
// prepare inputs (Though this is not necessaily required, no opened inputs will work, too
if (asioDriverInfo->inputChannels > kMaxInputChannels)
asioDriverInfo->inputBuffers = kMaxInputChannels;
else
asioDriverInfo->inputBuffers = asioDriverInfo->inputChannels;
for(i = 0; i < asioDriverInfo->inputBuffers; i++, info++)
{
info->isInput = ASIOTrue;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// prepare outputs
if (asioDriverInfo->outputChannels > kMaxOutputChannels)
asioDriverInfo->outputBuffers = kMaxOutputChannels;
else
asioDriverInfo->outputBuffers = asioDriverInfo->outputChannels;
for(i = 0; i < asioDriverInfo->outputBuffers; i++, info++)
{
info->isInput = ASIOFalse;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// create and activate buffers
result = ASIOCreateBuffers(asioDriverInfo->bufferInfos,
asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers,
asioDriverInfo->preferredSize, &asioCallbacks);
if (result == ASE_OK)
{
// now get all the buffer details, sample word length, name, word clock group and activation
for (i = 0; i < asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers; i++)
{
asioDriverInfo->channelInfos[i].channel = asioDriverInfo->bufferInfos[i].channelNum;
asioDriverInfo->channelInfos[i].isInput = asioDriverInfo->bufferInfos[i].isInput;
result = ASIOGetChannelInfo(&asioDriverInfo->channelInfos[i]);
if (result != ASE_OK)
break;
}
if (result == ASE_OK)
{
// get the input and output latencies
// Latencies often are only valid after ASIOCreateBuffers()
// (input latency is the age of the first sample in the currently returned audio block)
// (output latency is the time the first sample in the currently returned audio block requires to get to the output)
result = ASIOGetLatencies(&asioDriverInfo->inputLatency, &asioDriverInfo->outputLatency);
if (result == ASE_OK)
printf ("ASIOGetLatencies (input: %d, output: %d);\n", asioDriverInfo->inputLatency, asioDriverInfo->outputLatency);
}
}
return result;
}
int main(int argc, char* argv[])
{
// load the driver, this will setup all the necessary internal data structures
if (loadAsioDriver (ASIO_DRIVER_NAME))
{
// initialize the driver
if (ASIOInit (&asioDriverInfo.driverInfo) == ASE_OK)
{
printf ("asioVersion: %d\n"
"driverVersion: %d\n"
"Name: %s\n"
"ErrorMessage: %s\n",
asioDriverInfo.driverInfo.asioVersion, asioDriverInfo.driverInfo.driverVersion,
asioDriverInfo.driverInfo.name, asioDriverInfo.driverInfo.errorMessage);
if (init_asio_static_data (&asioDriverInfo) == 0)
{
// ASIOControlPanel(); you might want to check wether the ASIOControlPanel() can open
// set up the asioCallback structure and create the ASIO data buffer
asioCallbacks.bufferSwitch = &bufferSwitch;
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
asioCallbacks.asioMessage = &asioMessages;
asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
if (create_asio_buffers (&asioDriverInfo) == ASE_OK)
{
if (ASIOStart() == ASE_OK)
{
// Now all is up and running
fprintf (stdout, "\nASIO Driver started succefully.\n\n");
while (!asioDriverInfo.stopped)
{
#if WINDOWS
Sleep(100); // goto sleep for 100 milliseconds
#elif MAC
unsigned long dummy;
Delay (6, &dummy);
#endif
fprintf (stdout, "%d ms / %d ms / %d samples", asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)asioDriverInfo.samples);
// create a more readable time code format (the quick and dirty way)
double remainder = asioDriverInfo.tcSamples;
long hours = (long)(remainder / (asioDriverInfo.sampleRate * 3600));
remainder -= hours * asioDriverInfo.sampleRate * 3600;
long minutes = (long)(remainder / (asioDriverInfo.sampleRate * 60));
remainder -= minutes * asioDriverInfo.sampleRate * 60;
long seconds = (long)(remainder / asioDriverInfo.sampleRate);
remainder -= seconds * asioDriverInfo.sampleRate;
fprintf (stdout, " / TC: %2.2d:%2.2d:%2.2d:%5.5d", (long)hours, (long)minutes, (long)seconds, (long)remainder);
fprintf (stdout, " \r");
#if !MAC
fflush (stdout);
#endif
}
ASIOStop();
}
ASIODisposeBuffers();
}
}
ASIOExit();
}
asioDrivers->removeCurrentDriver();
}
return 0;
}
unsigned long get_sys_reference_time()
{ // get the system reference time
#if WINDOWS
return timeGetTime();
#elif MAC
static const double twoRaisedTo32 = 4294967296.;
UnsignedWide ys;
Microseconds(&ys);
double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
return (unsigned long)(r / 1000.);
#endif
}
+134
View File
@@ -0,0 +1,134 @@
# Microsoft Developer Studio Project File - Name="hostsample" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** NICHT BEARBEITEN **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=hostsample - Win32 Debug
!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
!MESSAGE
!MESSAGE NMAKE /f "hostsample.mak".
!MESSAGE
!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
!MESSAGE
!MESSAGE NMAKE /f "hostsample.mak" CFG="hostsample - Win32 Debug"
!MESSAGE
!MESSAGE Für die Konfiguration stehen zur Auswahl:
!MESSAGE
!MESSAGE "hostsample - Win32 Release" (basierend auf "Win32 (x86) Console Application")
!MESSAGE "hostsample - Win32 Debug" (basierend auf "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "hostsample - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "hostsample - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "hostsample - Win32 Release"
# Name "hostsample - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\common\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\pc\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=.\jahostsample.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\common\asio.h
# End Source File
# Begin Source File
SOURCE=..\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\pc\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\ginclude.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\ReadMe.txt
# End Source File
# End Target
# End Project
+29
View File
@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!
###############################################################################
Project: "hostsample"=.\hostsample.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
<html>
<body>
<pre>
<h1>Erstellungsprotokoll</h1>
<h3>
--------------------Konfiguration: hostsample - Win32 Debug--------------------
</h3>
<h3>Befehlszeilen</h3>
Erstellen der temporären Datei "F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E2.tmp" mit Inhalten
[
/nologo /MLd /W3 /Gm /GX /ZI /Od /I "../../common" /I "../../host" /I "../../host/pc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"Debug/" /Fp"Debug/hostsample.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
"E:\home\Develop\SDKs\ASIO\asiosdk2\host\pc\asiolist.cpp"
]
Creating command line "cl.exe @F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E2.tmp"
Erstellen der temporären Datei "F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E3.tmp" mit Inhalten
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/hostsample.pdb" /debug /machine:I386 /out:"Debug/hostsample.exe" /pdbtype:sept
.\Debug\asio.obj
.\Debug\asiodrivers.obj
.\Debug\asiolist.obj
.\Debug\jahostsample.obj
]
Erstellen der Befehlzeile "link.exe @F:\DOCUME~1\jens\LOCALS~1\Temp\RSP1E3.tmp"
<h3>Ausgabefenster</h3>
Kompilierung läuft...
asiolist.cpp
Linker-Vorgang läuft...
<h3>Ergebnisse</h3>
hostsample.exe - 0 Fehler, 0 Warnung(en)
</pre>
</body>
</html>
+583
View File
@@ -0,0 +1,583 @@
// hostsample.cpp : a simple ASIO host example.
// - instantiates the driver
// - get the information from the driver
// - built up some audio channels
// - plays silence for 20 seconds
// - destruct the driver
// Note: This sample cannot work with the "ASIO DirectX Driver" as it does
// not have a valid Application Window handle, which is used as sysRef
// on the Windows platform.
#include <stdio.h>
#include <string.h>
#include "asiosys.h"
#include "asio.h"
#include "asiodrivers.h"
#include "iasiodrv.h"
// name of the ASIO device to be used
#if WINDOWS
// #define ASIO_DRIVER_NAME "ASIO Multimedia Driver"
#define ASIO_DRIVER_NAME "ASIO Sample"
#elif MAC
// #define ASIO_DRIVER_NAME "Apple Sound Manager"
#define ASIO_DRIVER_NAME "ASIO Sample"
#endif
#define TEST_RUN_TIME 60.0 // run for 20 seconds
enum {
// number of input and outputs supported by the host application
// you can change these to higher or lower values
kMaxInputChannels = 32,
kMaxOutputChannels = 32
};
// internal data storage
typedef struct DriverInfo
{
// ASIOInit()
ASIODriverInfo driverInfo;
// ASIOGetChannels()
long inputChannels;
long outputChannels;
// ASIOGetBufferSize()
long minSize;
long maxSize;
long preferredSize;
long granularity;
// ASIOGetSampleRate()
ASIOSampleRate sampleRate;
// ASIOOutputReady()
bool postOutput;
// ASIOGetLatencies ()
long inputLatency;
long outputLatency;
// ASIOCreateBuffers ()
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
// ASIOGetChannelInfo()
ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
// The above two arrays share the same indexing, as the data in them are linked together
// Information from ASIOGetSamplePosition()
// data is converted to double floats for easier use, however 64 bit integer can be used, too
double nanoSeconds;
double samples;
double tcSamples; // time code samples
// bufferSwitchTimeInfo()
ASIOTime tInfo; // time info state
unsigned long sysRefTime; // system reference time, when bufferSwitch() was called
// Signal the end of processing in this example
bool stopped;
} DriverInfo;
DriverInfo asioDriverInfo = {0};
ASIOCallbacks asioCallbacks;
//----------------------------------------------------------------------------------
// some external references
extern AsioDrivers* asioDrivers;
bool loadAsioDriver(char *name);
// internal prototypes (required for the Metrowerks CodeWarrior compiler)
int main(int argc, char* argv[]);
long init_asio_static_data (DriverInfo *asioDriverInfo);
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo);
unsigned long get_sys_reference_time();
// callback prototypes
void bufferSwitch(long index, ASIOBool processNow);
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow);
void sampleRateChanged(ASIOSampleRate sRate);
long asioMessages(long selector, long value, void* message, double* opt);
//----------------------------------------------------------------------------------
long init_asio_static_data (DriverInfo *asioDriverInfo)
{ // collect the informational data of the driver
// get the number of available channels
if(ASIOGetChannels(&asioDriverInfo->inputChannels, &asioDriverInfo->outputChannels) == ASE_OK)
{
printf ("ASIOGetChannels (inputs: %d, outputs: %d);\n", asioDriverInfo->inputChannels, asioDriverInfo->outputChannels);
// get the usable buffer sizes
if(ASIOGetBufferSize(&asioDriverInfo->minSize, &asioDriverInfo->maxSize, &asioDriverInfo->preferredSize, &asioDriverInfo->granularity) == ASE_OK)
{
printf ("ASIOGetBufferSize (min: %d, max: %d, preferred: %d, granularity: %d);\n",
asioDriverInfo->minSize, asioDriverInfo->maxSize,
asioDriverInfo->preferredSize, asioDriverInfo->granularity);
// get the currently selected sample rate
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
{
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
if (asioDriverInfo->sampleRate <= 0.0 || asioDriverInfo->sampleRate > 96000.0)
{
// Driver does not store it's internal sample rate, so set it to a know one.
// Usually you should check beforehand, that the selected sample rate is valid
// with ASIOCanSampleRate().
if(ASIOSetSampleRate(44100.0) == ASE_OK)
{
if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
else
return -6;
}
else
return -5;
}
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
if(ASIOOutputReady() == ASE_OK)
asioDriverInfo->postOutput = true;
else
asioDriverInfo->postOutput = false;
printf ("ASIOOutputReady(); - %s\n", asioDriverInfo->postOutput ? "Supported" : "Not supported");
return 0;
}
return -3;
}
return -2;
}
return -1;
}
//----------------------------------------------------------------------------------
// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
#if NATIVE_INT64
#define ASIO64toDouble(a) (a)
#else
const double twoRaisedTo32 = 4294967296.;
#define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
#endif
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. This is omitted here for simplicity.
static processedSamples = 0;
// store the timeInfo for later use
asioDriverInfo.tInfo = *timeInfo;
// 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);
else
asioDriverInfo.nanoSeconds = 0;
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);
else
asioDriverInfo.tcSamples = 0;
// get the system reference time
asioDriverInfo.sysRefTime = get_sys_reference_time();
#if WINDOWS && _DEBUG
// a few debug messages for the Windows device driver developer
// tells you the time when driver got its interrupt and the delay until the app receives
// the event notification.
static double last_samples = 0;
char tmp[128];
sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples));
OutputDebugString (tmp);
last_samples = asioDriverInfo.samples;
#endif
// buffer size in samples
long buffSize = asioDriverInfo.preferredSize;
// perform the processing
for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
{
if (asioDriverInfo.bufferInfos[i].isInput == false)
{
// OK do processing for the outputs only
switch (asioDriverInfo.channelInfos[i].type)
{
case ASIOSTInt16LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24LSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32LSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
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
case ASIOSTInt32LSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTInt16MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
break;
case ASIOSTInt24MSB: // used for 20 bits as well
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
break;
case ASIOSTInt32MSB:
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
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
case ASIOSTInt32MSB16: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
break;
}
}
}
// finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
if (asioDriverInfo.postOutput)
ASIOOutputReady();
if (processedSamples >= asioDriverInfo.sampleRate * TEST_RUN_TIME) // roughly measured
asioDriverInfo.stopped = true;
else
processedSamples += buffSize;
return 0L;
}
//----------------------------------------------------------------------------------
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.
// as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs 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));
// 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)
timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
bufferSwitchTimeInfo (&timeInfo, index, processNow);
}
//----------------------------------------------------------------------------------
void sampleRateChanged(ASIOSampleRate sRate)
{
// 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
// might not have even changed, maybe only the sample rate status of an
// AES/EBU or S/PDIF digital input at the audio device.
// You might have to update time/sample related conversion routines, etc.
}
//----------------------------------------------------------------------------------
long asioMessages(long selector, long value, void* message, double* opt)
{
// currently the parameters "value", "message" and "opt" are not used.
long ret = 0;
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
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:
// 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;
}
//----------------------------------------------------------------------------------
ASIOError create_asio_buffers (DriverInfo *asioDriverInfo)
{ // create buffers for all inputs and outputs of the card with the
// preferredSize from ASIOGetBufferSize() as buffer size
long i;
ASIOError result;
// fill the bufferInfos from the start without a gap
ASIOBufferInfo *info = asioDriverInfo->bufferInfos;
// prepare inputs (Though this is not necessaily required, no opened inputs will work, too
if (asioDriverInfo->inputChannels > kMaxInputChannels)
asioDriverInfo->inputBuffers = kMaxInputChannels;
else
asioDriverInfo->inputBuffers = asioDriverInfo->inputChannels;
for(i = 0; i < asioDriverInfo->inputBuffers; i++, info++)
{
info->isInput = ASIOTrue;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// prepare outputs
if (asioDriverInfo->outputChannels > kMaxOutputChannels)
asioDriverInfo->outputBuffers = kMaxOutputChannels;
else
asioDriverInfo->outputBuffers = asioDriverInfo->outputChannels;
for(i = 0; i < asioDriverInfo->outputBuffers; i++, info++)
{
info->isInput = ASIOFalse;
info->channelNum = i;
info->buffers[0] = info->buffers[1] = 0;
}
// create and activate buffers
result = ASIOCreateBuffers(asioDriverInfo->bufferInfos,
asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers,
asioDriverInfo->preferredSize, &asioCallbacks);
if (result == ASE_OK)
{
// now get all the buffer details, sample word length, name, word clock group and activation
for (i = 0; i < asioDriverInfo->inputBuffers + asioDriverInfo->outputBuffers; i++)
{
asioDriverInfo->channelInfos[i].channel = asioDriverInfo->bufferInfos[i].channelNum;
asioDriverInfo->channelInfos[i].isInput = asioDriverInfo->bufferInfos[i].isInput;
result = ASIOGetChannelInfo(&asioDriverInfo->channelInfos[i]);
if (result != ASE_OK)
break;
}
if (result == ASE_OK)
{
// get the input and output latencies
// Latencies often are only valid after ASIOCreateBuffers()
// (input latency is the age of the first sample in the currently returned audio block)
// (output latency is the time the first sample in the currently returned audio block requires to get to the output)
result = ASIOGetLatencies(&asioDriverInfo->inputLatency, &asioDriverInfo->outputLatency);
if (result == ASE_OK)
printf ("ASIOGetLatencies (input: %d, output: %d);\n", asioDriverInfo->inputLatency, asioDriverInfo->outputLatency);
}
}
return result;
}
#define MAX_DRV_NAME 256
int main(int argc, char* argv[])
{
AsioDrivers drivers;
ASIOChannelInfo *pChannelInfoInput, *pChannelInfoOutput;
char **ppDriverNames;
long numInstalledDrivers, numInputs, numOutputs;
numInstalledDrivers = drivers.asioGetNumDev();
ppDriverNames = new char*[numInstalledDrivers];
for (int i=0; i < numInstalledDrivers; i++)
ppDriverNames[i] = new char[MAX_DRV_NAME];
drivers.getDriverNames(ppDriverNames, numInstalledDrivers);
printf("* Available ASIO-Drivers:\n");
for (i=0; i < numInstalledDrivers; i++)
printf("Driver #%d: %s\n",i+1,ppDriverNames[i]);
printf("\n");
// load the driver, this will setup all the necessary internal data structures
if (loadAsioDriver (ppDriverNames[0]))
{
// initialize the driver
if (ASIOInit (&asioDriverInfo.driverInfo) == ASE_OK)
{
printf ("asioVersion: %d\n"
"driverVersion: %d\n"
"Name: %s\n"
"ErrorMessage: %s\n",
asioDriverInfo.driverInfo.asioVersion, asioDriverInfo.driverInfo.driverVersion,
asioDriverInfo.driverInfo.name, asioDriverInfo.driverInfo.errorMessage);
ASIOGetChannels(&numInputs, &numOutputs);
pChannelInfoInput = new ASIOChannelInfo[numInputs];
pChannelInfoOutput = new ASIOChannelInfo[numOutputs];
for (i=0; i < numInputs; i++)
ASIOGetChannelInfoInput(&pChannelInfoInput[i], i);
for (i=0; i < numOutputs; i++)
ASIOGetChannelInfoOutput(&pChannelInfoOutput[i], i);
printf("* Input Channels:\n");
for (i=0; i < numInputs; i++)
{
printf("%s\n",pChannelInfoInput[i].name);
}
printf("* Out Channels:\n");
for (i=0; i < numOutputs; i++)
{
printf("%s\n",pChannelInfoOutput[i].name);
}
printf("\n");
if (init_asio_static_data (&asioDriverInfo) == 0)
{
// ASIOControlPanel(); you might want to check wether the ASIOControlPanel() can open
// set up the asioCallback structure and create the ASIO data buffer
asioCallbacks.bufferSwitch = &bufferSwitch;
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
asioCallbacks.asioMessage = &asioMessages;
asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
if (create_asio_buffers (&asioDriverInfo) == ASE_OK)
{
if (ASIOStart() == ASE_OK)
{
// Now all is up and running
fprintf (stdout, "\nASIO Driver started succefully.\n\n");
while (!asioDriverInfo.stopped)
{
#if WINDOWS
Sleep(100); // goto sleep for 100 milliseconds
#elif MAC
unsigned long dummy;
Delay (6, &dummy);
#endif
fprintf (stdout, "%d ms / %d ms / %d samples", asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)asioDriverInfo.samples);
// create a more readable time code format (the quick and dirty way)
double remainder = asioDriverInfo.tcSamples;
long hours = (long)(remainder / (asioDriverInfo.sampleRate * 3600));
remainder -= hours * asioDriverInfo.sampleRate * 3600;
long minutes = (long)(remainder / (asioDriverInfo.sampleRate * 60));
remainder -= minutes * asioDriverInfo.sampleRate * 60;
long seconds = (long)(remainder / asioDriverInfo.sampleRate);
remainder -= seconds * asioDriverInfo.sampleRate;
fprintf (stdout, " / TC: %2.2d:%2.2d:%2.2d:%5.5d", (long)hours, (long)minutes, (long)seconds, (long)remainder);
fprintf (stdout, " \r");
#if !MAC
fflush (stdout);
#endif
// asioDriverInfo.
}
ASIOStop();
}
ASIODisposeBuffers();
}
}
ASIOExit();
}
asioDrivers->removeCurrentDriver();
for (int i=0; i < numInstalledDrivers; i++)
delete [] ppDriverNames[i];
delete ppDriverNames;
delete [] pChannelInfoInput;
delete [] pChannelInfoOutput;
}
return 0;
}
unsigned long get_sys_reference_time()
{ // get the system reference time
#if WINDOWS
return timeGetTime();
#elif MAC
static const double twoRaisedTo32 = 4294967296.;
UnsignedWide ys;
Microseconds(&ys);
double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
return (unsigned long)(r / 1000.);
#endif
}
Executable
+2020
View File
File diff suppressed because it is too large Load Diff
Executable
+54
View File
@@ -0,0 +1,54 @@
ASIO 2.0 SDK Contents
---------------------
readme.txt - this file
ASIO SDK 2.pdf - ASIO SDK 2.0 specification
ASIO Licensing Agreement.rtf - Licencing Agreement
mac.sea.hqx - Macintosh CodeWarrior Pro 5 Projects
After de-Binhexing and Unstuffing the
mac folder should be on this same directory level
common:
asio.h - ASIO C definition
iasiodrv.h - interface definition for the ASIO driver class
asio.cpp - asio host interface (not used on Mac)
asiodrvr.h
asiodrvr.cpp - ASIO driver class base definition
combase.h
combase.cpp - COM base definitions (PC only)
dllentry.cpp - DLL functions (PC only)
register.cpp - driver self registration functionality
wxdebug.h
debugmessage.cpp - some debugging help
host:
asiodrivers.h
asiodrivers.cpp - ASIO driver managment (enumeration and instantiation)
ASIOConvertSamples.h
ASIOConvertSamples.cpp - sample data format conversion class
ginclude.h - platform specific definitions
host/mac:
asioshlib.cpp - asio.cpp for the Mac, resolves the symbols
codefragments.hpp
codefragments.cpp - code fragment loader
host/pc:
asiolist.h
asiolist.cpp - instantiates an ASIO driver via the COM model
host/sample:
hostsample.cpp - a simple console app which shows ASIO hosting
hostsample.dsp - MSVC++ 5.0 project
driver/asiosample:
asiosmpl.h
asiosmpl.cpp - ASIO 2.0 sample driver
wintimer.cpp - bufferSwitch() wakeup thread (Windows)
asiosample.def - Windows DLL module export definition
mactimer.cpp - bufferSwitch() wakeup thread (Macintosh)
macnanosecs.cpp - Macintosh system reference time
makesamp.cpp - Macintosh driver object instantiation
driver/asiosample/asiosample:
asiosample.dsp - MSVC++ 5.0 project