diff --git a/README.md b/README.md index e64d6f0..58f5d5f 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ Raspberry 4 (3B+) this software uses these programs: * Shifra Reed Solomon code: https://www.schifra.com/ (GPL V.2) * liquid-SDR: https://github.com/jgaeddert/liquid-dsp (MIT License) -* BASS Audio: https://www.un4seen.com/ (free for non-commercial use) +* libsoundio: https://github.com/andrewrk/libsoundio (MIT License) * fftw3: http://www.fftw.org (GPL V.2 or later) -* libcodec2 (Linux: standard lib, Windows: from freeDV) +* libcodec2: https://github.com/drowe67/codec2 (LGPL 2.1, Linux: standard lib, Windows: from freeDV) # Download alternatives * download from github and build from source diff --git a/WinRelease/bass.dll b/WinRelease/bass.dll deleted file mode 100755 index 4be4264..0000000 Binary files a/WinRelease/bass.dll and /dev/null differ diff --git a/WinRelease/basswasapi.dll b/WinRelease/basswasapi.dll deleted file mode 100755 index 41ed83e..0000000 Binary files a/WinRelease/basswasapi.dll and /dev/null differ diff --git a/WinRelease/hsmodem.exe b/WinRelease/hsmodem.exe deleted file mode 100755 index 1823757..0000000 Binary files a/WinRelease/hsmodem.exe and /dev/null differ diff --git a/WinRelease/hsmodem.iobj b/WinRelease/hsmodem.iobj deleted file mode 100755 index 054867d..0000000 Binary files a/WinRelease/hsmodem.iobj and /dev/null differ diff --git a/WinRelease/hsmodem.ipdb b/WinRelease/hsmodem.ipdb deleted file mode 100755 index 0d465db..0000000 Binary files a/WinRelease/hsmodem.ipdb and /dev/null differ diff --git a/WinRelease/hsmodem.pdb b/WinRelease/hsmodem.pdb deleted file mode 100755 index 2fe5355..0000000 Binary files a/WinRelease/hsmodem.pdb and /dev/null differ diff --git a/WinRelease/libsoundio.dll b/WinRelease/libsoundio.dll new file mode 100755 index 0000000..e9b8295 Binary files /dev/null and b/WinRelease/libsoundio.dll differ diff --git a/WinRelease/oscardata.exe b/WinRelease/oscardata.exe index 80be768..a1a49d6 100755 Binary files a/WinRelease/oscardata.exe and b/WinRelease/oscardata.exe differ diff --git a/hsmodem.wse b/hsmodem.wse new file mode 100755 index 0000000..e177ac2 --- /dev/null +++ b/hsmodem.wse @@ -0,0 +1,1043 @@ +Document Type: WSE +item: Global + Version=7.0 + Title=Multimedia High Speed Modem Installation + Flags=00010100 + Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + Copy Default=1 + Japanese Font Name=MS Gothic + Japanese Font Size=9 + Progress Bar DLL=%_WISE_%\Progress\WIZ%_EXE_OS_TYPE_%.DLL + Start Gradient=0 0 255 + End Gradient=0 0 0 + Windows Flags=00000100000000010010110000001000 + Log Pathname=%MAINDIR%\INSTALL.LOG + Message Font=MS Sans Serif + Font Size=8 + Pages Modified=00110001010100100000001000000001 + Extra Pages=00000000000000000000000000100000 + Disk Label=Default + Disk Filename=SETUP + Patch Flags=0000000000000001 + Patch Threshold=85 + Patch Memory=4000 + EXE Filename=hsmodem_setup.exe + FTP Cluster Size=20 + Per-User Version ID=1 + Dialogs Version=7 + Version File=V0.4 + Version Description=Multimedia High Speed Modem + Version Copyright=Kurt Moraw + Version Company=DJ0ABR + Step View=Simple + Variable Name1=_SYS_ + Variable Default1=C:\Windows\system32 + Variable Flags1=00001000 + Variable Name2=_WIN_ + Variable Default2=C:\Windows + Variable Flags2=00001000 + Variable Name3=_WISE_ + Variable Default3=C:\Program Files\Wise InstallBuilder + Variable Flags3=00001000 + Variable Name4=_ALIASNAME_ + Variable Flags4=00001000 + Variable Name5=_ALIASPATH_ + Variable Flags5=00001000 + Variable Name6=_ALIASTYPE_ + Variable Flags6=00001000 +end +item: Remark + Text=If you do not want Rem statements to appear when you create a new installation, +end +item: Remark + Text=open Empty Project.wse from the Template folder in the Wise application +end +item: Remark + Text=directory, delete the Rem statements, and select Save from the File menu. +end +item: Open/Close INSTALL.LOG + Flags=00000001 +end +item: Remark + Text=If the destination system does not have a writable Windows\System directory, system files will be written to the Windows\ directory +end +item: Check if File/Dir Exists + Pathname=%SYS% + Flags=10000100 +end +item: Set Variable + Variable=SYS + Value=%WIN% +end +item: End Block +end +item: Remark + Text=APPTITLE is the application title of the installation +end +item: Set Variable + Variable=APPTITLE + Value=Multimedia High Speed Modem + Flags=10000000 +end +item: Remark + Text=GROUP is the variable that holds the Program Files Group that shortcuts will be placed on the Windows Start Menu +end +item: Set Variable + Variable=GROUP + Value=Amsat + Flags=10000000 +end +item: Remark + Text=DISABLED variable is initialized for backward compatability +end +item: Set Variable + Variable=DISABLED + Value=! +end +item: Remark + Text=MAINDIR is the variable that holds the default destination directory +end +item: Set Variable + Variable=MAINDIR + Value=hsmodem + Flags=10000000 +end +item: Remark + Text=This IF/THEN/ELSE blocks reads the default Program Files and Common directories from the registry +end +item: Get Registry Key Value + Variable=COMMON + Key=SOFTWARE\Microsoft\Windows\CurrentVersion + Default=C:\Program Files\Common Files + Value Name=CommonFilesDir + Flags=00000100 +end +item: Get Registry Key Value + Variable=PROGRAM_FILES + Key=SOFTWARE\Microsoft\Windows\CurrentVersion + Default=C:\Program Files + Value Name=ProgramFilesDir + Flags=00000100 +end +item: Set Variable + Variable=MAINDIR + Value=%PROGRAM_FILES%\%MAINDIR% + Flags=00001100 +end +item: Set Variable + Variable=EXPLORER + Value=1 +end +item: Remark + Text=BACKUP is the variable that holds the path that all backup files will be copied to when overwritten +end +item: Set Variable + Variable=BACKUP + Value=%MAINDIR%\BACKUP + Flags=10000000 +end +item: Remark + Text=DOBACKUP determines if a backup will be performed. The possible values are A (do backup) or B (do not do backup) +end +item: Set Variable + Variable=DOBACKUP + Value=B + Flags=10000000 +end +item: Remark + Text=If COMPONENTS are enabled, the COMPONENTS variable is initialized with possible selections +end +item: Set Variable + Variable=COMPONENTS + Flags=10000000 +end +item: Remark + Text=BRANDING determines if the installation will be branded with a name and company. By default, this is written to the INST directory (installation media). +end +item: Set Variable + Variable=BRANDING + Value=0 +end +item: If/While Statement + Variable=BRANDING + Value=1 +end +item: Read INI Value + Variable=NAME + Pathname=%INST%\CUSTDATA.INI + Section=Registration + Item=Name +end +item: Read INI Value + Variable=COMPANY + Pathname=%INST%\CUSTDATA.INI + Section=Registration + Item=Company +end +item: If/While Statement + Variable=NAME +end +item: Set Variable + Variable=DOBRAND + Value=1 +end +item: Get System Information + Variable=NAME + Flags=00000110 +end +item: Get System Information + Variable=COMPANY + Flags=00000111 +end +item: End Block +end +item: End Block +end +item: Remark + Text=The Wizard Loop contains the dialog screens that the user sees in the installation +end +item: Remark + Text=If you would like to change the graphic on the dialog boxes, you need to change it by double-clicking on the Wizard Loop line and change the bitmap path. +end +item: Wizard Block + Direction Variable=DIRECTION + Display Variable=DISPLAY + Bitmap Pathname=%_WISE_%\DIALOGS\TEMPLATE\WIZARD.BMP + X Position=9 + Y Position=10 + Filler Color=8421376 + Dialog=Select Program Manager Group + Dialog=Select Backup Directory + Dialog=Display Registration Information + Dialog=Get Registration Information + Variable=GROUP + Variable=DOBACKUP + Variable=DOBRAND + Variable=DOBRAND + Value= + Value=A + Value=1 + Value=1 + Compare=0 + Compare=1 + Compare=0 + Compare=1 + Flags=00000011 +end +item: Remark + Text=If you need to change the size of your Custom Dialogs, you need only change the "Welcome" screen. +end +item: Remark + Text=It's size is the template for all following dialogs within the Wizard Loop. +end +item: Custom Dialog Set + Name=Welcome + Display Variable=DISPLAY + item: Dialog + Title=Welcome + Title French=Bienvenue + Title German=Willkommen + Title Portuguese=Bem-vindo + Title Spanish=Bienvenido + Title Italian=Benvenuto + Title Danish=Velkommen + Title Dutch=Welkom + Title Norwegian=Velkommen + Title Swedish=Välkommen + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=83 8 121 33 + Action=2 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000000000000000001011 + Pathname=%_WISE_%\dialogs\template\install.grf + Pathname French=%_WISE_%\dialogs\template\install.grf + Pathname German=%_WISE_%\dialogs\template\install.grf + Pathname Portuguese=%_WISE_%\dialogs\template\install.grf + Pathname Spanish=%_WISE_%\dialogs\template\install.grf + Pathname Italian=%_WISE_%\dialogs\template\install.grf + Pathname Danish=%_WISE_%\dialogs\template\install.grf + Pathname Dutch=%_WISE_%\dialogs\template\install.grf + Pathname Norwegian=%_WISE_%\dialogs\template\install.grf + Pathname Swedish=%_WISE_%\dialogs\template\install.grf + end + item: Static + Rectangle=121 10 258 44 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000000000000000000000 + Text=Welcome to %APPTITLE% Setup program. This program will install %APPTITLE% on your computer. + Text French=Bienvenue sur le programme d'installation %APPTITLE%. Ce programme va installer %APPTITLE% sur votre ordinateur. + Text German=Willkommen im Installationsprogramm für %APPTITLE%. Dieses Programm installiert %APPTITLE% auf Ihrem Computer. + Text Portuguese=Bem-vindo ao programa de configuração %APPTITLE%. Este programa instalará %APPTITLE% no seu computador + Text Spanish=Bienvenido al programa de Configuración %APPTITLE%. Este programa instalará %APPTITLE en su ordenador + Text Italian=Benvenuto nel programma di installazione di %APPTITLE%. Con questo programma puoi installare %APPTITLE% sul tuo computer. + Text Danish=Velkommen til %APPTITLE% installationsprogrammet. Dette program installerer %APPTITLE% på computeren. + Text Dutch=Welkom bij het %APPTITLE% installatieprogramma. Dit programma installeert %APPTITLE% op uw computer. + Text Norwegian=Velkommen til %APPTITLE% Oppsett-program. Dette programmet vil installere %APPTITLE% på datamaskinen din. + Text Swedish=Välkommen till installationsprogrammet för %APPTITLE%. Detta program installerar %APPTITLE% på din dator. + end + item: Static + Rectangle=90 45 260 175 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000000000000000000000 + Text=It is strongly recommended that you exit all Windows programs before running this Setup Program. + Text= + Text=Click Cancel to quit Setup and close any programs you have running. Click Next to continue with the Setup program . + Text= + Text=This program is free under the conditions of GPL V3 and the licenses of the 3rd party libraries. By installing and using this program, you agree to these licenses. + Text French=Il vous est fortement recommandé de fermer tous les programmes Windows avant d'exécuter le Programme d'Installation + Text French= + Text French=Cliquez sur Annuler pour quitter l'Installation et fermez tous les programmes actuellement utilisés. Cliquez sur Suivant pour continuer l'installation + Text French= + Text French=ATTENTION : Ce programme est protégé par la loi sur les droits d'exploitation et par les traités internationaux + Text French= + Text French=Toute reproduction ou distribution, même partielle, de ce programme qui n'aura pas reçu d'autorisation préalable fera l'objet de poursuites et sera sévèrement sanctionnée par le droit civil et pénal + Text German=Wir empfehlen nachdrücklich, vor Ausführen dieses Installationsprogramms alle Windows-Programme zu beenden. + Text German= + Text German=Auf Abbrechen klicken, um die Installation zu beenden und alle laufenden Programme zu schließen. Auf Weiter klicken, um mit dem Installationsprogramm zu beginnen. + Text German= + Text German=WARNUNG: Dieses Programm ist urheberrechtlich sowie durch internationale Verträge geschützt. + Text German= + Text German=Die unzulässige Vervielfältigung oder Verbreitung dieses Programms, ob ganz oder auszugsweise, kann schwere zivil- und strafrechtliche Konsequenzen nach sich ziehen und wird unter voller Ausschöpfung der Rechtsmittel geahndet. + Text Portuguese=Recomenda-se insistentemente que saia de todos os programas do Windows antes de executar este Programa de Configuração. + Text Portuguese= + Text Portuguese=Faça um clique sobre Cancelar para sair da Configuração e feche todos os programas que estiver a executar. Faça um clique sobre Próximo para continuar com o programa de configuração + Text Portuguese= + Text Portuguese=AVISO: Este programa está protegido pela lei de direitos do autor e tratados internacionais + Text Portuguese= + Text Portuguese=A reprodução e a distribuição sem autorização deste programa, ou qualquer parte dele, pode dar lugar à aplicação de severas sanções civis e criminais, e serão perseguidas à extensão máxima permitida pela lei. + Text Spanish=Se recomienda encarecidamente que salga de todos los programas Windows antes de ejecutar este programa de Configuración. + Text Spanish= + Text Spanish=Haga un clic en Cancelar para abandonar la Configuración y cerrar cualquier programa que haya estado ejecutando. Haga un clic en Siguiente para continuar con el programa de Configuración. + Text Spanish= + Text Spanish=AVISO: Este programa está protegido por las leyes de derechos de autor y tratados internacionales. + Text Spanish= + Text Spanish=La reproducción o distribución no autorizadas de este programa, o cualquier parte de él, podría dar como resultado rigurosas multas civiles y penales, y se entablará la máxima acción judicial que permita la ley. + Text Italian=Ti consigliamo di uscire da tutti i programmi Windows prima di eseguire questo programma di installazione. + Text Italian= + Text Italian=Fai clic su Annulla per uscire dal programma di installazione e chiudi tutti i programmi aperti. Fai clic su Avanti per continuare con il programma di Installazione. + Text Italian= + Text Italian=AVVERTENZA: Questo programma è protetto ai sensi delle norme di legge e delle convenzioni internazionali in materia di diritti di copyright. + Text Italian= + Text Italian=La riproduzione o la distribuzione totale o parziale non autorizzata di questo programma potrà essere soggetta a penalità civili e penali, e sarà punita con la massima severità possibile a norma di legge. + Text Danish=Det anbefales kraftigt at afslutte alle Windows programmer, inden man kører dette installationsprogram. + Text Danish= + Text Danish=Klik på Annuller for at forlade installationsprogrammet og lukke alle igangværende programmer. Klik på Næste for at fortsætte med installationsprogrammet. + Text Danish= + Text Danish=ADVARSEL: Dette program er beskyttet af copyright og internationale traktater. + Text Danish= + Text Danish=Uautoriseret gengivelse eller videresalg af dette program eller dele heraf kan føre til streng civil- og/eller kriminel stra. Retsforfølgning heraf vil finde sted i det videste omfang der hjemles muligt. + Text Dutch=Het wordt aangeraden om alle Windows programma's af te sluiten voordat u met de installatie van dit programma begint. + Text Dutch= + Text Dutch=Klik op Annuleren om de installatie te verlaten en eventueel nog lopende programma's af te sluiten. Klik op Volgende om verder te gaan met het Installatieprogramma. + Text Dutch= + Text Dutch=WAARSCHUWING: dit computerprogramma is auteursrechtelijk beschermd. + Text Dutch= + Text Dutch=Onrechtmatige verveelvoudiging of distributie van dit programma of een gedeelte ervan is verboden en strafbaar en zal met alle beschikbare juridische middelen worden bestreden. + Text Norwegian=Det anbefales på det sterkeste at du avslutter alle Windows-programmer før du kjører dette Oppsett-programmet. + Text Norwegian= + Text Norwegian=Velg Avbryt for å avbryte Oppsett og lukk alle programmer som er i bruk. Velg Neste for å fortsette med Oppsett-programmet. + Text Norwegian= + Text Norwegian=ADVARSEL: Dette programmet er beskyttet i henhold til lover om opphavsrett og internasjonale konvensjoner. + Text Norwegian= + Text Norwegian=Uautorisert kopiering eller distribuering av dette programmet eller deler av det, vil resultere i alvorlig sivil og kriminell straff og vil føre til saksmål i høyest mulig utstrekning i henhold til loven. + Text Swedish=Du tillråds bestämt att gå ur alla Windows-program innan du kör installationsprogrammet. + Text Swedish= + Text Swedish=Klicka på Avbryt för att gå ur installationsprogrammet och stäng eventuella program som du har laddade. Klicka på Nästa för att fortsätta med installationen. + Text Swedish= + Text Swedish=VARNING: Detta program är skyddat av upphovsrätten och internationella avtal. + Text Swedish= + Text Swedish=Om du utan tillstånd kopierar eller distribuerar detta program eller delar av det kan det bli allvarliga civilrättsliga och brottsrättliga straffpåföljder. Vi beivrar sådana överträdelser i den allra högsta utsträckning som lagen tillåter. + end + end +end +item: Custom Dialog Set + Name=Select Program Manager Group + Display Variable=DISPLAY + item: Dialog + Title=Select Program Manager Group + Title French=Sélectionnez le Groupe du Gestionnaire de Programmes + Title German=Programm-Managergruppe wählen + Title Portuguese=Seleccionar o Grupo Gestor de Programas + Title Spanish=Seleccione el Grupo del Administrador del Programa + Title Italian=Seleziona il gruppo Program Manager + Title Danish=Vælg Programstyringsgruppen + Title Dutch=Kies Programmabeheergroep. + Title Norwegian=Velg Programbehandlingsgruppen + Title Swedish=Välj grupp i Programhanteraren + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=130 185 172 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Flags=0000000000000001 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Back + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Slet + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 10 260 38 + Create Flags=01010000000000000000000000000000 + Text=Enter the name of the Program Manager group to add %APPTITLE% icons to: + Text French=Entrez le nom du groupe du Gestionnaire de Programmes où placer les icônes %APPTITLE% à : + Text German=Den Namen der Programm-Managergruppe wählen, in der die %APPTITLE%-Symbole gespeichert werden sollen: + Text Portuguese=Introduzir o nome do Grupo Gestor de Programa para acrescentar os ícones %APPTITLE% para: + Text Spanish=Introduzca el nombre del grupo del Administrador del Programa para añadir los iconos %APPTITLE para: + Text Italian=Inserisci il nome del gruppo Program Manager per aggiungere le icone di %APPTITLE% a: + Text Danish=Indtast navnet på Programstyringsgruppen der skal tilføjes %APPTITLE% elementer: + Text Dutch=Breng de naam van de programmabeheergroep in waaraan u %APPTITLE%-pictogrammen wilt toevoegen. + Text Norwegian=Tast inn navnet på programbehandlingsgruppen for å legge %APPTITLE%-ikoner til: + Text Swedish=Skriv in namnet på den grupp i Programhanteraren där du vill ha ikonerna för %APPTITLE%: + end + item: Combobox + Rectangle=90 42 260 172 + Variable=GROUP + Create Flags=01010000001000010000001100000001 + Flags=0000000000000001 + Text=%GROUP% + Text= + Text French=%GROUP% + Text French= + Text German=%GROUP% + Text German= + Text Portuguese=%GROUP% + Text Portuguese= + Text Spanish=%GROUP% + Text Spanish= + Text Italian=%GROUP% + Text Italian= + Text Danish=%GROUP% + Text Danish= + Text Dutch=%GROUP% + Text Dutch= + Text Norwegian=%GROUP% + Text Norwegian= + Text Swedish=%GROUP% + Text Swedish= + end + end +end +item: Custom Dialog Set + Name=Start Installation + Display Variable=DISPLAY + item: Dialog + Title=Start Installation + Title French=Commencer l'installation + Title German=Installation beginnen + Title Portuguese=Iniciar Instalação + Title Spanish=Comenzar la Instalación + Title Italian=Avvia Installazione + Title Danish=Start installationen + Title Dutch=Start de installatie + Title Norwegian=Start installeringen + Title Swedish=Starta installationen + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=130 185 172 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Tilbage + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 10 260 70 + Create Flags=01010000000000000000000000000000 + Text=You are now ready to install %APPTITLE%. + Text= + Text=Press the Next button to begin the installation or the Back button to reenter the installation information. + Text French=Vous êtes maintenant prêt à installer %APPTITLE% + Text French= + Text French=Cliquez sur Suivant pour commencer l'installation ou Retour pour entrer à nouveau les informations d'installation + Text German=Sie sind jetzt zur Installation von %APPTITLE% bereit. + Text German= + Text German=Auf die Schaltfläche Weiter klicken, um mit dem Start der Installation zu beginnen, oder auf die Schaltfläche Zurück, um die Installationsinformationen nochmals aufzurufen. + Text Portuguese=Está agora pronto para instalar %APPTITLE% + Text Portuguese= + Text Portuguese=Pressione o botão Próximo para começar a instalação ou o botão Retornar para introduzir novamente a informação sobre a instalação + Text Spanish=Ahora estará listo para instalar %APPTITLE%. + Text Spanish= + Text Spanish=Pulse el botón de Siguiente para comenzar la instalación o el botón Retroceder para volver a introducir la información sobre la instalación. + Text Italian=Sei pronto ad installare %APPTITLE%. + Text Italian= + Text Italian=Premi il tasto Avanti per iniziare l’installazione o il tasto Indietro per rientrare nuovamente nei dati sull’installazione + Text Danish=Du er nu klar til at installere %APPTITLE%. + Text Danish= + Text Danish=Klik på Næste for at starte installationen eller på Tilbage for at ændre installationsoplysningerne. + Text Dutch=U bent nu klaar om %APPTITLE% te installeren. + Text Dutch= + Text Dutch=Druk op Volgende om met de installatie te beginnen of op Terug om de installatie-informatie opnieuw in te voeren. + Text Norwegian=Du er nå klar til å installere %APPTITLE% + Text Norwegian= + Text Norwegian=Trykk på Neste-tasten for å starte installeringen, eller Tilbake-tasten for å taste inn installasjonsinformasjonen på nytt. + Text Swedish=Du är nu redo att installera %APPTITLE%. + Text Swedish= + Text Swedish=Tryck på Nästa för att starta installationen eller på Tillbaka för att skriva in installationsinformationen på nytt. + end + end +end +item: Remark + Text=This reinitialized the BACKUP directory so that it reflects the change the user made to MAINDIR +end +item: If/While Statement + Variable=DISPLAY + Value=Select Destination Directory +end +item: Set Variable + Variable=BACKUP + Value=%MAINDIR%\BACKUP +end +item: End Block +end +item: End Block +end +item: Remark + Text=When the BACKUP feature is enabled, the BACKUPDIR is initialized +end +item: If/While Statement + Variable=DOBACKUP + Value=A +end +item: Set Variable + Variable=BACKUPDIR + Value=%BACKUP% +end +item: End Block +end +item: Remark + Text=The BRANDING information is written to the INI file on the installation media. +end +item: If/While Statement + Variable=BRANDING + Value=1 +end +item: If/While Statement + Variable=DOBRAND + Value=1 +end +item: Edit INI File + Pathname=%INST%\CUSTDATA.INI + Settings=[Registration] + Settings=NAME=%NAME% + Settings=COMPANY=%COMPANY% + Settings= +end +item: End Block +end +item: End Block +end +item: Remark + Text=Begin writing to the INSTALL.LOG +end +item: Open/Close INSTALL.LOG +end +item: Remark + Text=Check free disk space calculates free disk space as well as component sizes. +end +item: Remark + Text=It should be located before all Install File actions. +end +item: Check Disk Space + Component=COMPONENTS +end +item: Remark + Text=This include script allows uninstall support +end +item: Include Script + Pathname=%_WISE_%\INCLUDE\uninstal.wse +end +item: Install File + Source=c:\tmp\WinRelease\Satellite-icon.ico + Destination=%MAINDIR%\Satellite-icon.ico + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\3000.pcm + Destination=%MAINDIR%\audio\3000.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\4000.pcm + Destination=%MAINDIR%\audio\4000.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\4410.pcm + Destination=%MAINDIR%\audio\4410.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\4800.pcm + Destination=%MAINDIR%\audio\4800.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\5500.pcm + Destination=%MAINDIR%\audio\5500.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\6000.pcm + Destination=%MAINDIR%\audio\6000.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\6600.pcm + Destination=%MAINDIR%\audio\6600.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\7200.pcm + Destination=%MAINDIR%\audio\7200.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\amsat.pcm + Destination=%MAINDIR%\audio\amsat.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\kbps.pcm + Destination=%MAINDIR%\audio\kbps.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\psk8.pcm + Destination=%MAINDIR%\audio\psk8.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\audio\qpsk.pcm + Destination=%MAINDIR%\audio\qpsk.pcm + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\bass.dll + Destination=%MAINDIR%\bass.dll + Flags=0000000010000011 +end +item: Install File + Source=c:\tmp\WinRelease\basswasapi.dll + Destination=%MAINDIR%\basswasapi.dll + Flags=0000000010000011 +end +item: Install File + Source=c:\tmp\WinRelease\hsmodem.exe + Destination=%MAINDIR%\hsmodem.exe + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\libcodec2.dll + Destination=%MAINDIR%\libcodec2.dll + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\libfftw3-3.dll + Destination=%MAINDIR%\libfftw3-3.dll + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\libgcc_s_dw2-1.dll + Destination=%MAINDIR%\libgcc_s_dw2-1.dll + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\libgcc_s_sjlj-1.dll + Destination=%MAINDIR%\libgcc_s_sjlj-1.dll + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\libliquid.dll + Destination=%MAINDIR%\libliquid.dll + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\liblpcnetfreedv.dll + Destination=%MAINDIR%\liblpcnetfreedv.dll + Flags=0000000010000010 +end +item: Install File + Source=c:\tmp\WinRelease\libwinpthread-1.dll + Destination=%MAINDIR%\libwinpthread-1.dll + Flags=0000000010000011 +end +item: Install File + Source=c:\tmp\WinRelease\oscardata.exe + Destination=%MAINDIR%\oscardata.exe + Flags=0000000010000011 +end +item: Remark + Text=This IF/THEN/ELSE reads the correct registry entries for shortcut/icon placement +end +item: Get Registry Key Value + Variable=STARTUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Start Menu\Programs\StartUp + Value Name=StartUp + Flags=00000010 +end +item: Get Registry Key Value + Variable=DESKTOPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Desktop + Value Name=Desktop + Flags=00000010 +end +item: Get Registry Key Value + Variable=STARTMENUDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Start Menu + Value Name=Start Menu + Flags=00000010 +end +item: Get Registry Key Value + Variable=GROUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Start Menu\Programs + Value Name=Programs + Flags=00000010 +end +item: Get Registry Key Value + Variable=CSTARTUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%STARTUPDIR% + Value Name=Common Startup + Flags=00000100 +end +item: Get Registry Key Value + Variable=CDESKTOPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%DESKTOPDIR% + Value Name=Common Desktop + Flags=00000100 +end +item: Get Registry Key Value + Variable=CSTARTMENUDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%STARTMENUDIR% + Value Name=Common Start Menu + Flags=00000100 +end +item: Get Registry Key Value + Variable=CGROUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%GROUPDIR% + Value Name=Common Programs + Flags=00000100 +end +item: Set Variable + Variable=CGROUP_SAVE + Value=%GROUP% +end +item: Set Variable + Variable=GROUP + Value=%GROUPDIR%\%GROUP% +end +item: Create Shortcut + Source=%MAINDIR%\oscardata.exe + Destination=%GROUP%\HSmodem.lnk + Working Directory=%MAINDIR% + Icon Number=0 + Icon Pathname=%MAINDIR%\Satellite-icon.ico + Key Type=1536 + Flags=00000001 +end +item: Remark + Text=All OCX/DLL/EXE files that are self-registered +end +item: Self-Register OCXs/DLLs + Description=Updating System Configuration, Please Wait... +end +item: Remark + Text=This Wizard Loop finalizes the install +end +item: Wizard Block + Direction Variable=DIRECTION + Display Variable=DISPLAY + Bitmap Pathname=%_WISE_%\DIALOGS\TEMPLATE\WIZARD.BMP + X Position=9 + Y Position=10 + Filler Color=8421440 + Flags=00000011 +end +item: Custom Dialog Set + Name=Finished + Display Variable=DISPLAY + item: Dialog + Title=Installation Complete + Title French=Installation en cours + Title German=Installation abgeschlossen + Title Portuguese=Instalação Completa + Title Spanish=Se ha completado la Instalación + Title Italian=Installazione completata + Title Danish=Installation gennemført + Title Dutch=Installatie afgerond + Title Norwegian=Installasjonen er fullført + Title Swedish=Installationen klar + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=170 185 212 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Finish > + Text French=&Terminer> + Text German=&Fertigstellen> + Text Portuguese=&Terminar > + Text Spanish=&Finalizar> + Text Italian=&Fine > + Text Danish=&Afslut > + Text Dutch=&Klaar> + Text Norwegian=&Avslutt> + Text Swedish=&Sluta> + end + item: Push Button + Control Name=CANCEL + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 10 260 63 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000000000000000000000 + Text=%APPTITLE% has been successfully installed. + Text= + Text= + Text=Press the Finish button to exit this installation. + Text= + Text French=L'installation de %APPTITLE% est réussie + Text French= + Text French= + Text French=Cliquez sur Terminer pour quitter cette installation + Text French= + Text German=%APPTITLE% wurde erfolgreich installiert. + Text German= + Text German= + Text German=Zum Beenden dieser Installation Fertigstellen anklicken. + Text German= + Text Portuguese=%APPTITLE% foi instalado com êxito + Text Portuguese= + Text Portuguese= + Text Portuguese=Pressionar o botão Terminar para sair desta instalação + Text Portuguese= + Text Spanish=%APPTITLE% se ha instalado con éxito. + Text Spanish= + Text Spanish= + Text Spanish=Pulse el botón de Finalizar para salir de esta instalación. + Text Spanish= + Text Italian=%APPTITLE% è stato installato. + Text Italian= + Text Italian= + Text Italian=Premi il pulsante Fine per uscire dal programma di installazione + Text Italian= + Text Danish=%APPTITLE% er nu installeret korrekt. + Text Danish= + Text Danish= + Text Danish=Klik på Afslut for at afslutte installationen. + Text Danish= + Text Dutch=%APPTITLE% is met succes geïnstalleerd. + Text Dutch= + Text Dutch= + Text Dutch=Druk op Klaar om deze installatie af te ronden. + Text Dutch= + Text Norwegian=Installasjonen av %APPTITLE% er vellykket. + Text Norwegian= + Text Norwegian= + Text Norwegian=Trykk på Avslutt-tasten for å avslutte denne installasjonen. + Text Norwegian= + Text Swedish=Installationen av %APPTITLE% har lyckats. + Text Swedish= + Text Swedish= + Text Swedish=Tryck på Sluta för att gå ur installationsprogrammet. + Text Swedish= + end + item: Push Button + Control Name=BACK + Rectangle=128 185 170 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Tilbage + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Set Control Attribute + Control Name=BACK + Operation=1 + end + item: Set Control Attribute + Control Name=CANCEL + Operation=1 + end + end +end +item: End Block +end +item: New Event + Name=Cancel +end +item: Remark + Text=This include script supports a rollback to preinstallation state if the user chooses to cancel before the installation is complete. +end +item: Include Script + Pathname=%_WISE_%\INCLUDE\rollback.wse +end diff --git a/hsmodem/Debug/audio.obj b/hsmodem/Debug/audio.obj deleted file mode 100755 index 68fb834..0000000 Binary files a/hsmodem/Debug/audio.obj and /dev/null differ diff --git a/hsmodem/Debug/audio_voice.obj b/hsmodem/Debug/audio_voice.obj deleted file mode 100755 index f23e7dd..0000000 Binary files a/hsmodem/Debug/audio_voice.obj and /dev/null differ diff --git a/hsmodem/Debug/audio_voice_wasapi.obj b/hsmodem/Debug/audio_voice_wasapi.obj deleted file mode 100755 index a61de16..0000000 Binary files a/hsmodem/Debug/audio_voice_wasapi.obj and /dev/null differ diff --git a/hsmodem/Debug/audio_wasapi.obj b/hsmodem/Debug/audio_wasapi.obj deleted file mode 100755 index e22ef94..0000000 Binary files a/hsmodem/Debug/audio_wasapi.obj and /dev/null differ diff --git a/hsmodem/Debug/codec2.obj b/hsmodem/Debug/codec2.obj deleted file mode 100755 index 662c16f..0000000 Binary files a/hsmodem/Debug/codec2.obj and /dev/null differ diff --git a/hsmodem/Debug/constellation.obj b/hsmodem/Debug/constellation.obj deleted file mode 100755 index 5dcf3d7..0000000 Binary files a/hsmodem/Debug/constellation.obj and /dev/null differ diff --git a/hsmodem/Debug/crc16.obj b/hsmodem/Debug/crc16.obj deleted file mode 100755 index c7174c9..0000000 Binary files a/hsmodem/Debug/crc16.obj and /dev/null differ diff --git a/hsmodem/Debug/fec.obj b/hsmodem/Debug/fec.obj deleted file mode 100755 index dce96aa..0000000 Binary files a/hsmodem/Debug/fec.obj and /dev/null differ diff --git a/hsmodem/Debug/fft.obj b/hsmodem/Debug/fft.obj deleted file mode 100755 index 510b5e2..0000000 Binary files a/hsmodem/Debug/fft.obj and /dev/null differ diff --git a/hsmodem/Debug/frame_packer.obj b/hsmodem/Debug/frame_packer.obj deleted file mode 100755 index fa2b8a5..0000000 Binary files a/hsmodem/Debug/frame_packer.obj and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.Build.CppClean.log b/hsmodem/Debug/hsmodem.Build.CppClean.log deleted file mode 100755 index cdeeab3..0000000 --- a/hsmodem/Debug/hsmodem.Build.CppClean.log +++ /dev/null @@ -1,29 +0,0 @@ -e:\funk\hsmodem\hsmodem\debug\vc140.pdb -e:\funk\hsmodem\hsmodem\debug\vc140.idb -e:\funk\hsmodem\hsmodem\debug\audio.obj -e:\funk\hsmodem\hsmodem\debug\audio_voice.obj -e:\funk\hsmodem\hsmodem\debug\audio_voice_wasapi.obj -e:\funk\hsmodem\hsmodem\debug\audio_wasapi.obj -e:\funk\hsmodem\hsmodem\debug\codec2.obj -e:\funk\hsmodem\hsmodem\debug\constellation.obj -e:\funk\hsmodem\hsmodem\debug\crc16.obj -e:\funk\hsmodem\hsmodem\debug\fec.obj -e:\funk\hsmodem\hsmodem\debug\fft.obj -e:\funk\hsmodem\hsmodem\debug\frame_packer.obj -e:\funk\hsmodem\hsmodem\debug\hsmodem.obj -e:\funk\hsmodem\hsmodem\debug\liquid_if.obj -e:\funk\hsmodem\hsmodem\debug\main_helper.obj -e:\funk\hsmodem\hsmodem\debug\scrambler.obj -e:\funk\hsmodem\hsmodem\debug\speed.obj -e:\funk\hsmodem\hsmodem\debug\symboltracker.obj -e:\funk\hsmodem\hsmodem\debug\udp.obj -e:\funk\hsmodem\hsmodem\debug\voiceprocessor.obj -e:\funk\hsmodem\debug\hsmodem.ilk -e:\funk\hsmodem\debug\hsmodem.exe -e:\funk\hsmodem\debug\hsmodem.pdb -e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\cl.command.1.tlog -e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\cl.read.1.tlog -e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\cl.write.1.tlog -e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\link.command.1.tlog -e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\link.read.1.tlog -e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\link.write.1.tlog diff --git a/hsmodem/Debug/hsmodem.log b/hsmodem/Debug/hsmodem.log deleted file mode 100755 index fe1ec07..0000000 --- a/hsmodem/Debug/hsmodem.log +++ /dev/null @@ -1,22 +0,0 @@ - liquid_if.cpp - hsmodem.cpp - fft.cpp - audio_wasapi.cpp - audio.cpp - Code wird generiert... - Kompilieren... - voiceprocessor.cpp - udp.cpp - symboltracker.cpp - speed.cpp - scrambler.cpp - main_helper.cpp - frame_packer.cpp - fec.cpp - crc16.cpp - constellation.cpp - codec2.cpp - audio_voice_wasapi.cpp - audio_voice.cpp - Code wird generiert... - hsmodem.vcxproj -> E:\funk\hsmodem\Debug\hsmodem.exe diff --git a/hsmodem/Debug/hsmodem.obj b/hsmodem/Debug/hsmodem.obj deleted file mode 100755 index 29a7fc1..0000000 Binary files a/hsmodem/Debug/hsmodem.obj and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.tlog/CL.command.1.tlog b/hsmodem/Debug/hsmodem.tlog/CL.command.1.tlog deleted file mode 100755 index d1f7787..0000000 Binary files a/hsmodem/Debug/hsmodem.tlog/CL.command.1.tlog and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.tlog/CL.read.1.tlog b/hsmodem/Debug/hsmodem.tlog/CL.read.1.tlog deleted file mode 100755 index 48aea88..0000000 Binary files a/hsmodem/Debug/hsmodem.tlog/CL.read.1.tlog and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.tlog/CL.write.1.tlog b/hsmodem/Debug/hsmodem.tlog/CL.write.1.tlog deleted file mode 100755 index 8d37c1d..0000000 Binary files a/hsmodem/Debug/hsmodem.tlog/CL.write.1.tlog and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.tlog/hsmodem.lastbuildstate b/hsmodem/Debug/hsmodem.tlog/hsmodem.lastbuildstate deleted file mode 100755 index a88860f..0000000 --- a/hsmodem/Debug/hsmodem.tlog/hsmodem.lastbuildstate +++ /dev/null @@ -1,2 +0,0 @@ -#TargetFrameworkVersion=v4.0:PlatformToolSet=v140_xp:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=8.1 -Debug|Win32|E:\funk\hsmodem\| diff --git a/hsmodem/Debug/hsmodem.tlog/link.command.1.tlog b/hsmodem/Debug/hsmodem.tlog/link.command.1.tlog deleted file mode 100755 index 6870f52..0000000 Binary files a/hsmodem/Debug/hsmodem.tlog/link.command.1.tlog and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.tlog/link.read.1.tlog b/hsmodem/Debug/hsmodem.tlog/link.read.1.tlog deleted file mode 100755 index 33a5c18..0000000 Binary files a/hsmodem/Debug/hsmodem.tlog/link.read.1.tlog and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.tlog/link.write.1.tlog b/hsmodem/Debug/hsmodem.tlog/link.write.1.tlog deleted file mode 100755 index a679723..0000000 Binary files a/hsmodem/Debug/hsmodem.tlog/link.write.1.tlog and /dev/null differ diff --git a/hsmodem/Debug/hsmodem.vcxproj.FileListAbsolute.txt b/hsmodem/Debug/hsmodem.vcxproj.FileListAbsolute.txt deleted file mode 100755 index e69de29..0000000 diff --git a/hsmodem/Debug/liquid_if.obj b/hsmodem/Debug/liquid_if.obj deleted file mode 100755 index bcbf5ef..0000000 Binary files a/hsmodem/Debug/liquid_if.obj and /dev/null differ diff --git a/hsmodem/Debug/main_helper.obj b/hsmodem/Debug/main_helper.obj deleted file mode 100755 index a3f88d3..0000000 Binary files a/hsmodem/Debug/main_helper.obj and /dev/null differ diff --git a/hsmodem/Debug/scrambler.obj b/hsmodem/Debug/scrambler.obj deleted file mode 100755 index f7aa14b..0000000 Binary files a/hsmodem/Debug/scrambler.obj and /dev/null differ diff --git a/hsmodem/Debug/speed.obj b/hsmodem/Debug/speed.obj deleted file mode 100755 index 9e9a2cc..0000000 Binary files a/hsmodem/Debug/speed.obj and /dev/null differ diff --git a/hsmodem/Debug/symboltracker.obj b/hsmodem/Debug/symboltracker.obj deleted file mode 100755 index 62a1dbe..0000000 Binary files a/hsmodem/Debug/symboltracker.obj and /dev/null differ diff --git a/hsmodem/Debug/udp.obj b/hsmodem/Debug/udp.obj deleted file mode 100755 index a2f5d72..0000000 Binary files a/hsmodem/Debug/udp.obj and /dev/null differ diff --git a/hsmodem/Debug/vc140.idb b/hsmodem/Debug/vc140.idb deleted file mode 100755 index 28d3cad..0000000 Binary files a/hsmodem/Debug/vc140.idb and /dev/null differ diff --git a/hsmodem/Debug/vc140.pdb b/hsmodem/Debug/vc140.pdb deleted file mode 100755 index 222804a..0000000 Binary files a/hsmodem/Debug/vc140.pdb and /dev/null differ diff --git a/hsmodem/Debug/voiceprocessor.obj b/hsmodem/Debug/voiceprocessor.obj deleted file mode 100755 index b64cc70..0000000 Binary files a/hsmodem/Debug/voiceprocessor.obj and /dev/null differ diff --git a/hsmodem/Makefile b/hsmodem/Makefile index ff13508..bf4f82c 100755 --- a/hsmodem/Makefile +++ b/hsmodem/Makefile @@ -8,11 +8,12 @@ # This will copy the sharded libs to its final location. CXXFLAGS = -Wall -O3 -std=c++0x -Wno-write-strings -Wno-narrowing -LDFLAGS = -lpthread -lrt -lsndfile -lasound -lm -lopus -lbassopus -lbass -lbassenc_opus -lbassenc -lfftw3 -lfftw3_threads -lliquid -lcodec2 -OBJ = hsmodem.o constellation.o crc16.o frame_packer.o main_helper.o scrambler.o speed.o fec.o audio.o udp.o fft.o liquid_if.o symboltracker.o audio_voice.o voiceprocessor.o codec2.o +LDFLAGS = -lpthread -lrt -lsndfile -lasound -lm -lopus -lfftw3 -lfftw3_threads -lliquid -lcodec2 -lsoundio +OBJ = hsmodem.o constellation.o crc16.o frame_packer.o main_helper.o scrambler.o speed.o fec.o udp.o fft.o liquid_if.o symboltracker.o voiceprocessor.o codec2.o soundio.o fifo.o announcement.o fifo_voice.o voiceio.o default: $(OBJ) mkdir -p ../hsmodemLinux + cp ../oscardata/oscardata/bin/Release/oscardata.exe ../hsmodemLinux g++ $(CXXFLAGS) -o ../hsmodemLinux/hsmodem $(OBJ) $(LDFLAGS) clean: diff --git a/hsmodem/Release/audio.obj b/hsmodem/Release/audio.obj deleted file mode 100755 index b221788..0000000 Binary files a/hsmodem/Release/audio.obj and /dev/null differ diff --git a/hsmodem/Release/audio_voice.obj b/hsmodem/Release/audio_voice.obj deleted file mode 100755 index 5e0cb3e..0000000 Binary files a/hsmodem/Release/audio_voice.obj and /dev/null differ diff --git a/hsmodem/Release/audio_voice_wasapi.obj b/hsmodem/Release/audio_voice_wasapi.obj deleted file mode 100755 index 6e3b626..0000000 Binary files a/hsmodem/Release/audio_voice_wasapi.obj and /dev/null differ diff --git a/hsmodem/Release/audio_wasapi.obj b/hsmodem/Release/audio_wasapi.obj deleted file mode 100755 index b65c2f2..0000000 Binary files a/hsmodem/Release/audio_wasapi.obj and /dev/null differ diff --git a/hsmodem/Release/codec2.obj b/hsmodem/Release/codec2.obj deleted file mode 100755 index 5e5013f..0000000 Binary files a/hsmodem/Release/codec2.obj and /dev/null differ diff --git a/hsmodem/Release/constellation.obj b/hsmodem/Release/constellation.obj deleted file mode 100755 index 4a35b8e..0000000 Binary files a/hsmodem/Release/constellation.obj and /dev/null differ diff --git a/hsmodem/Release/crc16.obj b/hsmodem/Release/crc16.obj deleted file mode 100755 index b607d7c..0000000 Binary files a/hsmodem/Release/crc16.obj and /dev/null differ diff --git a/hsmodem/Release/fec.obj b/hsmodem/Release/fec.obj deleted file mode 100755 index eeb11b3..0000000 Binary files a/hsmodem/Release/fec.obj and /dev/null differ diff --git a/hsmodem/Release/fft.obj b/hsmodem/Release/fft.obj deleted file mode 100755 index df7f26b..0000000 Binary files a/hsmodem/Release/fft.obj and /dev/null differ diff --git a/hsmodem/Release/frame_packer.obj b/hsmodem/Release/frame_packer.obj deleted file mode 100755 index 565ed79..0000000 Binary files a/hsmodem/Release/frame_packer.obj and /dev/null differ diff --git a/hsmodem/Release/hsmodem.Build.CppClean.log b/hsmodem/Release/hsmodem.Build.CppClean.log deleted file mode 100755 index 3eee5d7..0000000 --- a/hsmodem/Release/hsmodem.Build.CppClean.log +++ /dev/null @@ -1,28 +0,0 @@ -e:\funk\hsmodem\hsmodem\release\vc140.pdb -e:\funk\hsmodem\hsmodem\release\voiceprocessor.obj -e:\funk\hsmodem\hsmodem\release\udp.obj -e:\funk\hsmodem\hsmodem\release\symboltracker.obj -e:\funk\hsmodem\hsmodem\release\speed.obj -e:\funk\hsmodem\hsmodem\release\scrambler.obj -e:\funk\hsmodem\hsmodem\release\main_helper.obj -e:\funk\hsmodem\hsmodem\release\liquid_if.obj -e:\funk\hsmodem\hsmodem\release\hsmodem.obj -e:\funk\hsmodem\hsmodem\release\frame_packer.obj -e:\funk\hsmodem\hsmodem\release\fft.obj -e:\funk\hsmodem\hsmodem\release\fec.obj -e:\funk\hsmodem\hsmodem\release\crc16.obj -e:\funk\hsmodem\hsmodem\release\constellation.obj -e:\funk\hsmodem\hsmodem\release\codec2.obj -e:\funk\hsmodem\hsmodem\release\audio_wasapi.obj -e:\funk\hsmodem\hsmodem\release\audio_voice_wasapi.obj -e:\funk\hsmodem\hsmodem\release\audio_voice.obj -e:\funk\hsmodem\hsmodem\release\audio.obj -e:\funk\hsmodem\winrelease\hsmodem.exe -e:\funk\hsmodem\winrelease\hsmodem.pdb -e:\funk\hsmodem\hsmodem\..\winrelease\hsmodem.exe -e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.command.1.tlog -e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.read.1.tlog -e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.write.1.tlog -e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.command.1.tlog -e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.read.1.tlog -e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.write.1.tlog diff --git a/hsmodem/Release/hsmodem.log b/hsmodem/Release/hsmodem.log deleted file mode 100755 index 47c0fc8..0000000 --- a/hsmodem/Release/hsmodem.log +++ /dev/null @@ -1,24 +0,0 @@ - audio.cpp - audio_voice.cpp - audio_voice_wasapi.cpp - audio_wasapi.cpp - codec2.cpp - constellation.cpp - crc16.cpp - fec.cpp - fft.cpp - frame_packer.cpp - hsmodem.cpp - liquid_if.cpp - main_helper.cpp - scrambler.cpp - speed.cpp - symboltracker.cpp - udp.cpp - voiceprocessor.cpp - Code wird generiert. - 0 of 574 functions ( 0.0%) were compiled, the rest were copied from previous compilation. - 0 functions were new in current compilation - 0 functions had inline decision re-evaluated but remain unchanged - Codegenerierung ist abgeschlossen. - hsmodem.vcxproj -> E:\funk\hsmodem\hsmodem\..\WinRelease\hsmodem.exe diff --git a/hsmodem/Release/hsmodem.obj b/hsmodem/Release/hsmodem.obj deleted file mode 100755 index 8fe8d41..0000000 Binary files a/hsmodem/Release/hsmodem.obj and /dev/null differ diff --git a/hsmodem/Release/hsmodem.tlog/CL.command.1.tlog b/hsmodem/Release/hsmodem.tlog/CL.command.1.tlog deleted file mode 100755 index d2a90b4..0000000 Binary files a/hsmodem/Release/hsmodem.tlog/CL.command.1.tlog and /dev/null differ diff --git a/hsmodem/Release/hsmodem.tlog/CL.read.1.tlog b/hsmodem/Release/hsmodem.tlog/CL.read.1.tlog deleted file mode 100755 index e759a6b..0000000 Binary files a/hsmodem/Release/hsmodem.tlog/CL.read.1.tlog and /dev/null differ diff --git a/hsmodem/Release/hsmodem.tlog/CL.write.1.tlog b/hsmodem/Release/hsmodem.tlog/CL.write.1.tlog deleted file mode 100755 index 55f5f67..0000000 Binary files a/hsmodem/Release/hsmodem.tlog/CL.write.1.tlog and /dev/null differ diff --git a/hsmodem/Release/hsmodem.tlog/hsmodem.lastbuildstate b/hsmodem/Release/hsmodem.tlog/hsmodem.lastbuildstate deleted file mode 100755 index d1d5971..0000000 --- a/hsmodem/Release/hsmodem.tlog/hsmodem.lastbuildstate +++ /dev/null @@ -1,2 +0,0 @@ -#TargetFrameworkVersion=v4.0:PlatformToolSet=v140_xp:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=8.1 -Release|Win32|E:\funk\hsmodem\| diff --git a/hsmodem/Release/hsmodem.tlog/link.command.1.tlog b/hsmodem/Release/hsmodem.tlog/link.command.1.tlog deleted file mode 100755 index 297bc55..0000000 Binary files a/hsmodem/Release/hsmodem.tlog/link.command.1.tlog and /dev/null differ diff --git a/hsmodem/Release/hsmodem.tlog/link.read.1.tlog b/hsmodem/Release/hsmodem.tlog/link.read.1.tlog deleted file mode 100755 index 9208fb2..0000000 Binary files a/hsmodem/Release/hsmodem.tlog/link.read.1.tlog and /dev/null differ diff --git a/hsmodem/Release/hsmodem.tlog/link.write.1.tlog b/hsmodem/Release/hsmodem.tlog/link.write.1.tlog deleted file mode 100755 index 9b44f8a..0000000 Binary files a/hsmodem/Release/hsmodem.tlog/link.write.1.tlog and /dev/null differ diff --git a/hsmodem/Release/hsmodem.vcxproj.FileListAbsolute.txt b/hsmodem/Release/hsmodem.vcxproj.FileListAbsolute.txt deleted file mode 100755 index e69de29..0000000 diff --git a/hsmodem/Release/liquid_if.obj b/hsmodem/Release/liquid_if.obj deleted file mode 100755 index 6ba76f5..0000000 Binary files a/hsmodem/Release/liquid_if.obj and /dev/null differ diff --git a/hsmodem/Release/main_helper.obj b/hsmodem/Release/main_helper.obj deleted file mode 100755 index 5fd7653..0000000 Binary files a/hsmodem/Release/main_helper.obj and /dev/null differ diff --git a/hsmodem/Release/scrambler.obj b/hsmodem/Release/scrambler.obj deleted file mode 100755 index b0c4906..0000000 Binary files a/hsmodem/Release/scrambler.obj and /dev/null differ diff --git a/hsmodem/Release/speed.obj b/hsmodem/Release/speed.obj deleted file mode 100755 index 35bcf56..0000000 Binary files a/hsmodem/Release/speed.obj and /dev/null differ diff --git a/hsmodem/Release/symboltracker.obj b/hsmodem/Release/symboltracker.obj deleted file mode 100755 index 3bdf2e4..0000000 Binary files a/hsmodem/Release/symboltracker.obj and /dev/null differ diff --git a/hsmodem/Release/udp.obj b/hsmodem/Release/udp.obj deleted file mode 100755 index b9c5bb4..0000000 Binary files a/hsmodem/Release/udp.obj and /dev/null differ diff --git a/hsmodem/Release/vc140.pdb b/hsmodem/Release/vc140.pdb deleted file mode 100755 index c4fc26b..0000000 Binary files a/hsmodem/Release/vc140.pdb and /dev/null differ diff --git a/hsmodem/Release/voiceprocessor.obj b/hsmodem/Release/voiceprocessor.obj deleted file mode 100755 index 6963142..0000000 Binary files a/hsmodem/Release/voiceprocessor.obj and /dev/null differ diff --git a/hsmodem/SharedLibs/aarch64/libbass.so b/hsmodem/SharedLibs/aarch64/libbass.so deleted file mode 100644 index 2fadd03..0000000 Binary files a/hsmodem/SharedLibs/aarch64/libbass.so and /dev/null differ diff --git a/hsmodem/SharedLibs/aarch64/libbassenc.so b/hsmodem/SharedLibs/aarch64/libbassenc.so deleted file mode 100644 index 07f4a62..0000000 Binary files a/hsmodem/SharedLibs/aarch64/libbassenc.so and /dev/null differ diff --git a/hsmodem/SharedLibs/aarch64/libbassenc_opus.so b/hsmodem/SharedLibs/aarch64/libbassenc_opus.so deleted file mode 100644 index a34c136..0000000 Binary files a/hsmodem/SharedLibs/aarch64/libbassenc_opus.so and /dev/null differ diff --git a/hsmodem/SharedLibs/aarch64/libbassopus.so b/hsmodem/SharedLibs/aarch64/libbassopus.so deleted file mode 100644 index 4c8c0a4..0000000 Binary files a/hsmodem/SharedLibs/aarch64/libbassopus.so and /dev/null differ diff --git a/hsmodem/SharedLibs/windows/bass.dll b/hsmodem/SharedLibs/windows/bass.dll deleted file mode 100755 index 4be4264..0000000 Binary files a/hsmodem/SharedLibs/windows/bass.dll and /dev/null differ diff --git a/hsmodem/SharedLibs/windows/basswasapi.dll b/hsmodem/SharedLibs/windows/basswasapi.dll deleted file mode 100755 index 41ed83e..0000000 Binary files a/hsmodem/SharedLibs/windows/basswasapi.dll and /dev/null differ diff --git a/hsmodem/SharedLibs/x86_64/libbass.so b/hsmodem/SharedLibs/x86_64/libbass.so deleted file mode 100644 index 8839178..0000000 Binary files a/hsmodem/SharedLibs/x86_64/libbass.so and /dev/null differ diff --git a/hsmodem/SharedLibs/x86_64/libbassenc.so b/hsmodem/SharedLibs/x86_64/libbassenc.so deleted file mode 100644 index 8701b4b..0000000 Binary files a/hsmodem/SharedLibs/x86_64/libbassenc.so and /dev/null differ diff --git a/hsmodem/SharedLibs/x86_64/libbassenc_opus.so b/hsmodem/SharedLibs/x86_64/libbassenc_opus.so deleted file mode 100644 index ca8b113..0000000 Binary files a/hsmodem/SharedLibs/x86_64/libbassenc_opus.so and /dev/null differ diff --git a/hsmodem/SharedLibs/x86_64/libbassopus.so b/hsmodem/SharedLibs/x86_64/libbassopus.so deleted file mode 100644 index 7d231f0..0000000 Binary files a/hsmodem/SharedLibs/x86_64/libbassopus.so and /dev/null differ diff --git a/hsmodem/announcement.cpp b/hsmodem/announcement.cpp new file mode 100755 index 0000000..bf589a4 --- /dev/null +++ b/hsmodem/announcement.cpp @@ -0,0 +1,127 @@ +/* +* High Speed modem to transfer data in a 2,7kHz SSB channel +* ========================================================= +* Author: DJ0ABR +* +* (c) DJ0ABR +* www.dj0abr.de +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* announcement.c ... sends the *.pcm files to the playback device +* +* +*/ + +#include "hsmodem.h" + +typedef struct _AUDIOFILES_ { + char fn[256]; + int duration; +} AUDIOFILES; + +AUDIOFILES audiofiles[12] = +{ + {"amsat", 1100}, + {"qpsk", 1100}, + {"psk8", 1100}, + {"3000", 600}, + {"4000", 600}, + {"4410", 900}, + {"4800", 900}, + {"5500", 900}, + {"6000", 600}, + {"6600", 900}, + {"7200", 900}, + {"kbps", 1000}, +}; + +char* getAudiofn(int aidx, char* ext) +{ + static char filename[300]; + strcpy(filename, "audio/"); + strcat(filename, audiofiles[aidx].fn); + strcat(filename, ext); + return filename; +} + +void playAudioFLAC(int aidx) +{ + int resamp = 0; + int len; + int16_t d[100]; + printf("play:%s, caprate:%d\n", getAudiofn(aidx, ".pcm"),caprate); + FILE* fp = fopen(getAudiofn(aidx, ".pcm"), "rb"); + if (fp) + { + while ((len = fread(d, sizeof(int16_t), 100, fp))) + { + for (int i = 0; i < len; i++) + { + float f = (float)d[i]; + f /= 32768; + io_pb_write_fifo(f); + + if (caprate == 48000) + { + if (++resamp >= 9) + { + resamp = 0; + io_pb_write_fifo(f); + } + } + + // sync with soundcard + while (io_pb_fifo_usedspace() > 10000) sleep_ms(1); + } + if (len != 100) break; + } + fclose(fp); + } + else + printf("audio file not found\n"); +} + +int ann_running = 0; +int transmissions = 10000; + +void sendAnnouncement() +{ + if (announcement == 0) return; + + if (++transmissions >= announcement) + { + ann_running = 1; + transmissions = 0; + + playAudioFLAC(0); + if (bitsPerSymbol == 2) playAudioFLAC(1); + else playAudioFLAC(2); + switch (linespeed) + { + case 3000: playAudioFLAC(3); break; + case 4000: playAudioFLAC(4); break; + case 4410: playAudioFLAC(5); break; + case 4800: playAudioFLAC(6); break; + case 5500: playAudioFLAC(7); break; + case 6000: playAudioFLAC(8); break; + case 6600: playAudioFLAC(9); break; + case 7200: playAudioFLAC(10); break; + } + playAudioFLAC(11); + + ann_running = 0; + } +} diff --git a/hsmodem/audio.cpp b/hsmodem/audio.cpp deleted file mode 100755 index 4546b92..0000000 --- a/hsmodem/audio.cpp +++ /dev/null @@ -1,804 +0,0 @@ -/* -* High Speed modem to transfer data in a 2,7kHz SSB channel -* ========================================================= -* Author: DJ0ABR -* -* (c) DJ0ABR -* www.dj0abr.de -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* audio.c ... functions to handle audio in/out via a soundcard -* uses the "BASS" library -* -* captures samples from the sound card. -* Samples are 32-bit floats in a range of -1 to +1 -* get these samples from the thread safe fifo: cap_read_fifo(&floatvariable) -* -* plays samples to the sound card -* Samples are 32-bit floats in a range of -1 to +1 -* play the samples by calling the thread save function: pb_write_fifo(floatsample) -* -*/ - -#include "hsmodem.h" - -BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user); -DWORD CALLBACK WriteStream(HSTREAM handle, float *buffer, DWORD length, void *user); -int pb_read_fifo(float *data, int elements); -void cap_write_fifo(float sample); -int pb_fifo_freespace(int nolock); -void init_pipes(); - -HRECORD rchan = 0; // recording channel -BASS_INFO info; -HSTREAM stream = 0; - -int openpbdev = -1; -int opencapdev = -1; - -float softwareCAPvolume = 0.5; - -void showDeviceInfo(BASS_DEVICEINFO info) -{ - printf("Name:%s driver:%s flags:%d:", info.name, info.driver,info.flags); - if (info.flags & BASS_DEVICE_ENABLED) printf("%s\n","BASS_DEVICE_ENABLED "); - if (info.flags & BASS_DEVICE_DEFAULT) printf("%s\n","BASS_DEVICE_DEFAULT "); - if (info.flags & BASS_DEVICE_INIT) printf("%s\n","BASS_DEVICE_INIT "); - if (info.flags & BASS_DEVICE_LOOPBACK) printf("%s\n","BASS_DEVICE_LOOPBACK "); - if (info.flags & BASS_DEVICE_TYPE_DIGITAL) printf("%s\n","BASS_DEVICE_TYPE_DIGITAL "); - if (info.flags & BASS_DEVICE_TYPE_DISPLAYPORT) printf("%s\n","BASS_DEVICE_TYPE_DISPLAYPORT "); - if (info.flags & BASS_DEVICE_TYPE_HANDSET) printf("%s\n","BASS_DEVICE_TYPE_HANDSET "); - if (info.flags & BASS_DEVICE_TYPE_HDMI) printf("%s\n","BASS_DEVICE_TYPE_HDMI "); - if (info.flags & BASS_DEVICE_TYPE_HEADPHONES) printf("%s\n","BASS_DEVICE_TYPE_HEADPHONES "); - if (info.flags & BASS_DEVICE_TYPE_HEADSET) printf("%s\n","BASS_DEVICE_TYPE_HEADSET "); - if (info.flags & BASS_DEVICE_TYPE_LINE) printf("%s\n","BASS_DEVICE_TYPE_LINE "); - if (info.flags & BASS_DEVICE_TYPE_MICROPHONE) printf("%s\n","BASS_DEVICE_TYPE_MICROPHONE "); - if (info.flags & BASS_DEVICE_TYPE_NETWORK) printf("%s\n","BASS_DEVICE_TYPE_NETWORK "); - if (info.flags & BASS_DEVICE_TYPE_SPDIF) printf("%s\n","BASS_DEVICE_TYPE_SPDIF "); - if (info.flags & BASS_DEVICE_TYPE_SPEAKERS) printf("%s\n","BASS_DEVICE_TYPE_SPEAKERS "); - -} - -void showDeviceInfoWasabi(BASS_WASAPI_DEVICEINFO info, int devnum) -{ - printf("%d: Name:%s defperiod:%f flags:%d minperiod:%f mixchans:%d mixfreq:%d type:%d ", devnum, info.name, info.defperiod, info.flags, info.minperiod,info.mixchans, info.mixfreq,info.type); - if (info.flags & BASS_DEVICE_ENABLED) printf("%s\n", "BASS_DEVICE_ENABLED "); - if (info.flags & BASS_DEVICE_DEFAULT) printf("%s\n", "BASS_DEVICE_DEFAULT "); - if (info.flags & BASS_DEVICE_INIT) printf("%s\n", "BASS_DEVICE_INIT "); - if (info.flags & BASS_DEVICE_LOOPBACK) printf("%s\n", "BASS_DEVICE_LOOPBACK "); - if (info.flags & BASS_DEVICE_TYPE_DIGITAL) printf("%s\n", "BASS_DEVICE_TYPE_DIGITAL "); - if (info.flags & BASS_DEVICE_TYPE_DISPLAYPORT) printf("%s\n", "BASS_DEVICE_TYPE_DISPLAYPORT "); - if (info.flags & BASS_DEVICE_TYPE_HANDSET) printf("%s\n", "BASS_DEVICE_TYPE_HANDSET "); - if (info.flags & BASS_DEVICE_TYPE_HDMI) printf("%s\n", "BASS_DEVICE_TYPE_HDMI "); - if (info.flags & BASS_DEVICE_TYPE_HEADPHONES) printf("%s\n", "BASS_DEVICE_TYPE_HEADPHONES "); - if (info.flags & BASS_DEVICE_TYPE_HEADSET) printf("%s\n", "BASS_DEVICE_TYPE_HEADSET "); - if (info.flags & BASS_DEVICE_TYPE_LINE) printf("%s\n", "BASS_DEVICE_TYPE_LINE "); - if (info.flags & BASS_DEVICE_TYPE_MICROPHONE) printf("%s\n", "BASS_DEVICE_TYPE_MICROPHONE "); - if (info.flags & BASS_DEVICE_TYPE_NETWORK) printf("%s\n", "BASS_DEVICE_TYPE_NETWORK "); - if (info.flags & BASS_DEVICE_TYPE_SPDIF) printf("%s\n", "BASS_DEVICE_TYPE_SPDIF "); - if (info.flags & BASS_DEVICE_TYPE_SPEAKERS) printf("%s\n", "BASS_DEVICE_TYPE_SPEAKERS "); - printf("\n"); -} - -uint8_t devstring[MAXDEVSTRLEN +100]; -char PBdevs[100][256]; // stores the device names, just for diagnosis, has no real fuction -char CAPdevs[100][256]; - -// index is enumerated number, 0=default -AUDIODEVS audioPBdevs[100]; -AUDIODEVS audioCAPdevs[100]; -int pbanz = 0, capanz = 0; - -// populate audio device list -void readAudioDevs() -{ - int a; - pbanz = 0; - capanz = 0; - - // enter default device manually - audioPBdevs[pbanz].bassdev = -1; - strcpy(audioPBdevs[pbanz].name, "Default"); - pbanz++; - - audioCAPdevs[capanz].bassdev = -1; - strcpy(audioCAPdevs[capanz].name, "Default"); - capanz++; - -#ifdef _LINUX_ - BASS_DEVICEINFO info; - for (a = 1; BASS_GetDeviceInfo(a, &info); a++) - { - //showDeviceInfo(info); - if (info.flags & BASS_DEVICE_ENABLED && !(info.flags & BASS_DEVICE_LOOPBACK)) - { - if (!strstr(info.name, "efault")) - { - audioPBdevs[pbanz].bassdev = a; - strncpy(audioPBdevs[pbanz].name, info.name, 255); - audioPBdevs[pbanz].name[255] = 0; - strncpy(audioPBdevs[pbanz].id, info.driver, 255); - pbanz++; - } - } - } - - for (a = 1; BASS_RecordGetDeviceInfo(a, &info); a++) - { - //showDeviceInfo(info); - if (info.flags & BASS_DEVICE_ENABLED && !(info.flags & BASS_DEVICE_LOOPBACK)) - { - if (!strstr(info.name, "efault")) - { - audioCAPdevs[capanz].bassdev = a; - strncpy(audioCAPdevs[capanz].name, info.name, 255); - audioCAPdevs[capanz].name[255] = 0; - strncpy(audioCAPdevs[capanz].id, info.driver, 255); - capanz++; - } - } - } -#endif - -#ifdef _WIN32_ - BASS_WASAPI_DEVICEINFO info; - for (a = 0; BASS_WASAPI_GetDeviceInfo(a, &info); a++) - { - //showDeviceInfoWasabi(info,a); - if (!(info.flags & BASS_DEVICE_INPUT) && (info.flags & BASS_DEVICE_ENABLED) && !(info.flags & BASS_DEVICE_LOOPBACK)) - { - if (!strstr(info.name, "efault")) - { - audioPBdevs[pbanz].bassdev = a; - strncpy(audioPBdevs[pbanz].name, info.name, 255); - audioPBdevs[pbanz].name[255] = 0; - strncpy(audioPBdevs[pbanz].id, info.id, 255); - pbanz++; - } - } - - if ((info.flags & BASS_DEVICE_INPUT) && (info.flags & BASS_DEVICE_ENABLED) && !(info.flags & BASS_DEVICE_LOOPBACK)) - { - if (!strstr(info.name, "efault")) - { - audioCAPdevs[capanz].bassdev = a; - strncpy(audioCAPdevs[capanz].name, info.name, 255); - audioCAPdevs[capanz].name[255] = 0; - strncpy(audioCAPdevs[capanz].id, info.id, 255); - capanz++; - } - } - } -#endif -} - -void printAudioDevs() -{ - printf("PB devices:\n"); - for (int i = 0; i < pbanz; i++) - printf("idx:%d ID:%s bass:%d name:%s\n", i, audioPBdevs[i].id, audioPBdevs[i].bassdev, audioPBdevs[i].name); - - printf("CAP devices:\n"); - for (int i = 0; i < capanz; i++) - printf("idx:%d ID:%s bass:%d name:%s\n", i, audioCAPdevs[i].id, audioCAPdevs[i].bassdev, audioCAPdevs[i].name); -} - -// build string of audio device name, to be sent to application as response to Broadcast search -// starting with PB devices, sperarator ^, capture devices -// separator between devices: ~ -void buildUdpAudioList() -{ - memset(devstring, 0, sizeof(devstring)); - devstring[0] = ' '; // placeholder for ID for this UDP message - devstring[1] = '0' + init_audio_result; - devstring[2] = '0' + init_voice_result; - - //printf("init_voice_result:%d\n", devstring[2]); - - - // playback devices - for (int i = 0; i < pbanz; i++) - { - sprintf((char*)devstring + strlen((char*)devstring), "%d: ", i); - strcat((char*)devstring, audioPBdevs[i].name); - strcat((char*)devstring, "~"); // audio device separator - } - - strcat((char*)(devstring + 1), "^"); // PB, CAP separator - - // capture devices - for (int i = 0; i < capanz; i++) - { - sprintf((char*)devstring + strlen((char*)devstring), "%d: ", i); - strcat((char*)devstring, audioCAPdevs[i].name); - strcat((char*)devstring, "~"); // audio device separator - } - - devstring[0] = 3; // ID for this UDP message -} - -uint8_t* getAudioDevicelist(int *len) -{ - // update Status - devstring[1] = '0' + init_audio_result; - devstring[2] = '0' + init_voice_result; - - *len = strlen((char*)(devstring+1))+1; - return devstring; -} - -// read audio device list at program start, or if something went wrong -void readAudioDevices() -{ - readAudioDevs(); - //printAudioDevs(); - buildUdpAudioList(); - return; -} - -// ret: 0=ok, -1=system error, 1=pb error 2=cap error 3=pb+cap error -int init_audio(int setpbdev, int setcapdev) -{ -static int f = 1; -int ret = 0; - - if (f == 1) - { - // do only once after program start - f = 0; - readAudioDevices(); - init_pipes(); - } - - // translate requested device numbers to bass device numbers - if (setpbdev < 0 || setpbdev >= pbanz) setpbdev = 0; - if (setcapdev < 0 || setcapdev >= capanz) setcapdev = 0; - - int pbdev = -1; - if (setpbdev >=0 && setpbdev < pbanz) pbdev = audioPBdevs[setpbdev].bassdev; - int capdev = -2; - if (setcapdev >= 0 && setcapdev < capanz) capdev = audioCAPdevs[setcapdev].bassdev; - - printf("init audio, caprate:%d\n",caprate); - printf("requested PB device: %d bassno:%d name:%s\n", setpbdev, pbdev, audioPBdevs[setpbdev].name); - printf("requested CAP device: %d bassno:%d name:%s\n", setcapdev, capdev, audioCAPdevs[setcapdev].name); - - // check the correct BASS was loaded - if (HIWORD(BASS_GetVersion()) != BASSVERSION) - { - printf("An incorrect version of BASS was loaded\n"); - return 3; - } - -#ifdef _WIN32_ - // use WASAPI for Windows to get exclusive access to sound card - return init_wasapi(pbdev, capdev); -#endif - -#ifdef _LINUX_ - close_audio(); - - // ===== PLAYBACK ====== - - // initialize default output device - if (!BASS_Init(pbdev, caprate, 0, NULL, NULL)) - { - printf("Can't initialize output device: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - - // read real device number - int device = BASS_GetDevice(); - if (device == -1) - { - printf("BASS_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - pbdev = device; - openpbdev = pbdev; - printf("real BASS PB Device No: %d\n", pbdev); - - // set play callback - BASS_GetInfo(&info); - stream = BASS_StreamCreate(info.freq, CHANNELS, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream, 0); // sample: 32 bit float - BASS_ChannelSetAttribute(stream, BASS_ATTRIB_BUFFER, 0); // no buffering for minimum latency - BASS_ChannelPlay(stream, FALSE); // start it - } - } - - // ===== CAPTURE ==== - - // initalize default recording device - if (!BASS_RecordInit(capdev)) - { - printf("Can't initialize recording device: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - - // read real device number - int device = BASS_RecordGetDevice(); - if (device == -1) - { - printf("BASS_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - capdev = device; - printf("real BASS CAP Device No: %d\n", capdev); - - // set capture callback - if (rchan) BASS_ChannelStop(rchan); - rchan = BASS_RecordStart(caprate, CHANNELS, BASS_SAMPLE_FLOAT, RecordingCallback, 0); - if (!rchan) - { - printf("Can't start capturing: %d\n", BASS_ErrorGetCode()); - ret |= 2; - } - else - opencapdev = capdev; - } - } - - if(ret == 0) - printf("audio started successfully for PBdev:%d and CAPdev:%d\n", openpbdev, opencapdev); - else - { - opencapdev = -1; - openpbdev = -1; - readAudioDevices(); - } - if (ret == 1) - printf("audio initialized: PBerror CapOK\n"); - if (ret == 2) - printf("audio initialized: PBOK CapERROR\n"); - if (ret == 3) - printf("audio initialized: PBerror CapERROR\n"); - - return ret; -#endif -} - -#ifdef _LINUX_ -int selectPBdevice() -{ - if (!BASS_SetDevice(openpbdev)) - { - printf("BASS_SetDevice: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); - } - else - return 1; - - return 0; -} - -int selectCAPdevice() -{ - if (!BASS_SetDevice(opencapdev)) - { - //printf("BASS_SetDevice: %d err:%d\n", opencapdev, BASS_ErrorGetCode()); - } - else - return 1; - - return 0; -} - -void close_audio() -{ - if(stream != 0) - { - printf("close Audio Devices\n"); - selectCAPdevice(); - BASS_ChannelStop(rchan); - int rr = BASS_RecordFree(); - if (!rr) printf("Bass_RecordFree error: %d\n", BASS_ErrorGetCode()); - - selectPBdevice(); - BASS_StreamFree(stream); - int r = BASS_Free(); - if(!r) printf("Bass_Free error: %d\n", BASS_ErrorGetCode()); - stream = 0; - } -} - -void setPBvolume(int v) -{ - // the volume comes in % 0..99 - // map to 0..1 - float vf = v; - vf /= 100; - - //printf("set PB volume to:%d / %f [0..1]\n", v, vf ); - - if(selectPBdevice()) - if (!BASS_SetVolume(vf)) - printf("setPBvolume: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); -} - -void setCAPvolume(int v) -{ - // the volume comes in % 0..99 - // map to min/maxPBvol - float vf = v; - vf /= 100; - - //printf("set CAP volume to:%d / %f [0..1]\n", v, vf); - - if (selectCAPdevice()) - { - if (!BASS_RecordSetInput(-1, BASS_INPUT_ON, vf)) - printf("setCAPvolume: %d err:%d\n", opencapdev, BASS_ErrorGetCode()); - else - softwareCAPvolume = 1; - } - else - { - softwareCAPvolume = (float)v; - softwareCAPvolume /= 50; - } -} - -// capture callback -BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user) -{ - //printf("captured %ld samples, channels:%d\n",length/sizeof(float),CHANNELS); - //measure_speed(length/sizeof(float)); - - float *fbuffer = (float *)buffer; - //showbytestringf((char*)"cap:", fbuffer, 10); - //printf("w:%ld ",length/sizeof(float)); - for(unsigned int i=0; i<(length/sizeof(float)); i+=CHANNELS) - { - //printf("%f\n",fbuffer[i]); - cap_write_fifo(fbuffer[i]); - } - - return TRUE; // continue recording -} - -// play callback -// length: bytes. float=4byte, 2channels, so it requests samples*8 -DWORD CALLBACK WriteStream(HSTREAM handle, float *buffer, DWORD length, void *user) -{ - //printf("requested %ld samples\n", length / sizeof(float)); - int ret = pb_read_fifo(buffer, length / sizeof(float)); - if(ret == 0) - { - // fifo empty, send 00 - memset(buffer,0,length); - } - return length; -} - -#endif - -// set volume -void setVolume(int pbcap, int v) -{ - if (pbcap == 0) setPBvolume(v); - else setCAPvolume(v); -} - - -// ================ thread safe fifo for audio callback routines =============== - -#ifdef _WIN32_ -CRITICAL_SECTION cap_crit_sec; -CRITICAL_SECTION pb_crit_sec; -#define CAP_LOCK EnterCriticalSection(&cap_crit_sec) -#define PB_LOCK EnterCriticalSection(&pb_crit_sec) -void CAP_UNLOCK() -{ - if (&cap_crit_sec != NULL) - LeaveCriticalSection(&cap_crit_sec); -} -void PB_UNLOCK() -{ - if (&pb_crit_sec != NULL) - LeaveCriticalSection(&pb_crit_sec); -} -#endif - -#ifdef _LINUX_ -pthread_mutex_t cap_crit_sec; -pthread_mutex_t pb_crit_sec; -#define CAP_LOCK pthread_mutex_lock(&cap_crit_sec) -void CAP_UNLOCK() { pthread_mutex_unlock(&cap_crit_sec); } -#define PB_LOCK pthread_mutex_lock(&pb_crit_sec) -void PB_UNLOCK() { pthread_mutex_unlock(&pb_crit_sec); } -#endif - -#define AUDIO_PLAYBACK_BUFLEN (48000 * 10) // space for 10 seconds of samples -#define AUDIO_CAPTURE_BUFLEN 24000 // space for 0.5s - -int cap_wridx=0; -int cap_rdidx=0; -float cap_buffer[AUDIO_CAPTURE_BUFLEN]; - -int pb_wridx=0; -int pb_rdidx=0; -float pb_buffer[AUDIO_PLAYBACK_BUFLEN]; - -void init_pipes() -{ -#ifdef _WIN32_ - if (&cap_crit_sec != NULL) DeleteCriticalSection(&cap_crit_sec); - InitializeCriticalSection(&cap_crit_sec); - - if (&pb_crit_sec != NULL) DeleteCriticalSection(&pb_crit_sec); - InitializeCriticalSection(&pb_crit_sec); -#endif -} - -// write one sample into the fifo -// overwrite old data if the fifo is full -void cap_write_fifo(float sample) -{ - if (((cap_wridx + 1) % AUDIO_CAPTURE_BUFLEN) == cap_rdidx) - { - printf("cap fifo full\n"); - } - - CAP_LOCK; - cap_buffer[cap_wridx] = sample; - if(++cap_wridx >= AUDIO_CAPTURE_BUFLEN) cap_wridx = 0; - CAP_UNLOCK(); - - // if monitoring is activated then write it also to the voice fifo - if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN) - toVoice(sample); -} - -int cap_read_fifo(float *data) -{ - CAP_LOCK; - - if (cap_rdidx == cap_wridx) - { - // Fifo empty, no data available - CAP_UNLOCK(); - return 0; - } - - *data = cap_buffer[cap_rdidx]; - if(++cap_rdidx >= AUDIO_CAPTURE_BUFLEN) cap_rdidx = 0; - CAP_UNLOCK(); - - return 1; -} - -void cap_write_fifo_clear() -{ - cap_wridx = cap_rdidx = 0; -} - -int cap_fifo_freespace() -{ - int freebuf = 0; - - CAP_LOCK; - - int elemInFifo = (cap_wridx + AUDIO_CAPTURE_BUFLEN - cap_rdidx) % AUDIO_CAPTURE_BUFLEN; - freebuf = AUDIO_CAPTURE_BUFLEN - elemInFifo; - - CAP_UNLOCK(); - - return freebuf; -} - -int cap_fifo_usedPercent() -{ - int fs = cap_fifo_freespace(); - int used = AUDIO_CAPTURE_BUFLEN - fs; - used = (used * 100) / AUDIO_CAPTURE_BUFLEN; - return used; -} - - -void pb_write_fifo(float sample) -{ - PB_LOCK; - - // check if there is free space in fifo - if(pb_fifo_freespace(1) == 0) - { - PB_UNLOCK(); - printf("************* pb fifo full\n"); - return; - } - - pb_buffer[pb_wridx] = sample; - if(++pb_wridx >= AUDIO_PLAYBACK_BUFLEN) pb_wridx = 0; - PB_UNLOCK(); - //printf("write: pbw:%d pbr:%d\n",pb_wridx,pb_rdidx); -} - -void pb_write_fifo_clear() -{ - pb_wridx = pb_rdidx = 0; -} - -int pb_fifo_usedBlocks() -{ - int fs = pb_fifo_freespace(0); - int used = AUDIO_PLAYBACK_BUFLEN - fs; - used /= (txinterpolfactor * UDPBLOCKLEN * 8 / bitsPerSymbol); - return used; -} - -int pb_fifo_freespace(int nolock) -{ -int freebuf = 0; - - if(nolock == 0) PB_LOCK; - - int elemInFifo = (pb_wridx + AUDIO_PLAYBACK_BUFLEN - pb_rdidx) % AUDIO_PLAYBACK_BUFLEN; - freebuf = AUDIO_PLAYBACK_BUFLEN - elemInFifo; - - if(nolock == 0) PB_UNLOCK(); - - //printf("fifolen:%d check: pbw:%d pbr:%d freebuf:%d\n",AUDIO_PLAYBACK_BUFLEN,pb_wridx,pb_rdidx,freebuf); - - return freebuf; -} - -int pb_fifo_usedspace() -{ - int anz = pb_fifo_freespace(0); - return AUDIO_PLAYBACK_BUFLEN - anz; -} - -// read elements floats from fifo or return 0 if not enough floats are available -int pb_read_fifo(float *data, int elements) -{ - //printf("pb read fifo: %d\n",elements); - PB_LOCK; - - int e = AUDIO_PLAYBACK_BUFLEN - pb_fifo_freespace(1); - if(e < elements) - { - // Fifo empty, no data available - PB_UNLOCK(); - //printf("pb fifo empty: TX underrun\n"); - //printf("pb fifo empty, need:%d have:%d size:%d\n",elements,e,AUDIO_PLAYBACK_BUFLEN); - return 0; - } - - for(int i=0; i= AUDIO_PLAYBACK_BUFLEN) pb_rdidx = 0; - } - //printf("read %d floats\n",elements); - - PB_UNLOCK(); - return 1; -} - -void clear_audio_fifos() -{ - pb_write_fifo_clear(); - cap_write_fifo_clear(); -} - -// ================ Play PCM Audio File =========================== - -typedef struct _AUDIOFILES_ { - char fn[256]; - int duration; -} AUDIOFILES; - -AUDIOFILES audiofiles[12] = -{ - {"amsat", 1100}, - {"qpsk", 1100}, - {"psk8", 1100}, - {"3000", 600}, - {"4000", 600}, - {"4410", 900}, - {"4800", 900}, - {"5500", 900}, - {"6000", 600}, - {"6600", 900}, - {"7200", 900}, - {"kbps", 1000}, -}; - -char* getAudiofn(int aidx, char *ext) -{ - static char filename[300]; - strcpy(filename, "audio/"); - strcat(filename, audiofiles[aidx].fn); - strcat(filename, ext); - return filename; -} - -void playAudioFLAC(int aidx) -{ - int resamp = 0; - int len; - int16_t d[100]; - printf("play:%s\n", getAudiofn(aidx, ".pcm")); - FILE *fp = fopen(getAudiofn(aidx,".pcm"), "rb"); - if (fp) - { - while ((len = fread(d, sizeof(int16_t), 100, fp))) - { - for (int i = 0; i < len; i++) - { - float f = (float)d[i]; - f /= 32768; - pb_write_fifo(f); - - if (caprate == 48000) - { - if (++resamp >= 9) - { - resamp = 0; - pb_write_fifo(f); - } - } - - // sync with soundcard - while (pb_fifo_usedspace() > 10000) sleep_ms(1); - } - if (len != 100) break; - } - fclose(fp); - } - else - printf("audio file not found\n"); -} - -int ann_running = 0; -int transmissions = 10000; - -void sendAnnouncement() -{ - if (announcement == 0) return; - - if (++transmissions >= announcement) - { - ann_running = 1; - transmissions = 0; - - playAudioFLAC(0); - if(bitsPerSymbol == 2) playAudioFLAC(1); - else playAudioFLAC(2); - switch (linespeed) - { - case 3000: playAudioFLAC(3); break; - case 4000: playAudioFLAC(4); break; - case 4410: playAudioFLAC(5); break; - case 4800: playAudioFLAC(6); break; - case 5500: playAudioFLAC(7); break; - case 6000: playAudioFLAC(8); break; - case 6600: playAudioFLAC(9); break; - case 7200: playAudioFLAC(10); break; - } - playAudioFLAC(11); - - ann_running = 0; - } -} - diff --git a/hsmodem/audio/sound0.pcm b/hsmodem/audio/sound0.pcm new file mode 100644 index 0000000..30bb530 Binary files /dev/null and b/hsmodem/audio/sound0.pcm differ diff --git a/hsmodem/audio/sound1.pcm b/hsmodem/audio/sound1.pcm new file mode 100644 index 0000000..a6e9d0a Binary files /dev/null and b/hsmodem/audio/sound1.pcm differ diff --git a/hsmodem/audio_voice.cpp b/hsmodem/audio_voice.cpp deleted file mode 100755 index d291e15..0000000 --- a/hsmodem/audio_voice.cpp +++ /dev/null @@ -1,500 +0,0 @@ -/* -* High Speed modem to transfer data in a 2,7kHz SSB channel -* ========================================================= -* Author: DJ0ABR -* -* (c) DJ0ABR -* www.dj0abr.de -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* audio.c ... very similar to audio.c but is used for Microphone / Loudspeaker -* -*/ - -#include "hsmodem.h" - -void init_pipes_voice(); -BOOL CALLBACK RecordingCallback_voice(HRECORD handle, const void* buffer, DWORD length, void* user); -DWORD CALLBACK WriteStream_voice(HSTREAM handle, float* buffer, DWORD length, void* user); -//void CALLBACK EncodeProc(HENCODE handle, DWORD channel, const void* buffer, DWORD length, void* user); -void cap_write_fifo_voice(float sample); -int pb_read_fifo_voice(float* data, int elements); -void setLSvolume(int v); -void setMICvolume(int v); - -extern AUDIODEVS audioPBdevs[100]; -extern AUDIODEVS audioCAPdevs[100]; -extern int pbanz; -extern int capanz; - - -HRECORD rchan_voice = 0; // recording channel -BASS_INFO info_voice; -HSTREAM stream_voice = 0; - -int openpbdev_voice = -1; -int opencapdev_voice = -1; -int caprate_voice = VOICE_SAMPRATE; - -int initialLSvol = -1; -int initialMICvol = -1; - -float softwareCAPvolume_voice = 1; - -// pbdev, capdev: -1=default device -int init_audio_voice(int setpbdev, int setcapdev) -{ - static int f = 1; - int ret = 0; - - if (f == 1) - { - // do only once after program start - f = 0; - init_pipes_voice(); - } - - // translate requested device numbers to bass device numbers - if (setpbdev < 0 || setpbdev >= pbanz) setpbdev = 0; - if (setcapdev < 0 || setcapdev >= capanz) setcapdev = 0; - - int pbdev = -1; - if (setpbdev >= 0 && setpbdev < pbanz) pbdev = audioPBdevs[setpbdev].bassdev; - int capdev = -2; - if (setcapdev >= 0 && setcapdev < capanz) capdev = audioCAPdevs[setcapdev].bassdev; - - printf("voice: init audio_voice, caprate:%d\n", caprate_voice); - printf("voice: requested LS device: %d bassno:%d name:%s\n", setpbdev, pbdev, audioPBdevs[setpbdev].name); - printf("voice: requested MIC device: %d bassno:%d name:%s\n", setcapdev, capdev, audioCAPdevs[setcapdev].name); - -#ifdef _WIN32_ - // use WASAPI for Windows to get exclusive access to sound card - return init_wasapi_voice(pbdev, capdev); -#endif - -#ifdef _LINUX_ - close_audio_voice(); - - if (VoiceAudioMode == 0) return 0; // Voice off - - // ===== PLAYBACK ====== - - // initialize default output device - if (!BASS_Init(pbdev, caprate_voice, 0, NULL, NULL)) - { - printf("voice: Can't initialize output device: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - close_audio_voice(); - ret = 1; - } - else - { - - // read real device number - int device = BASS_GetDevice(); - if (device == -1) - { - printf("voice: BASS_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - close_audio_voice(); - ret = 1; - } - else - { - pbdev = device; - openpbdev_voice = pbdev; - printf("voice: real BASS PB Device No: %d\n", pbdev); - - // set play callback - BASS_GetInfo(&info_voice); - stream_voice = BASS_StreamCreate(info_voice.freq, 2, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream_voice, 0); // sample: 32 bit float - BASS_ChannelSetAttribute(stream_voice, BASS_ATTRIB_BUFFER, 0); // no buffering for minimum latency - BASS_ChannelPlay(stream_voice, FALSE); // start it - - setLSvolume(initialLSvol); - } - } - - // ===== CAPTURE ==== - - // initalize default recording device - if (!BASS_RecordInit(capdev)) - { - printf("voice: Can't initialize recording device: %d err:%d\n", capdev, BASS_ErrorGetCode()); - close_audio_voice(); - ret |= 2; - } - else - { - - // read real device number - int device = BASS_RecordGetDevice(); - if (device == -1) - { - printf("voice: BASS_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode()); - close_audio_voice(); - ret |= 2; - } - else - { - capdev = device; - printf("voice: real BASS CAP Device No: %d\n", capdev); - - // set capture callback - rchan_voice = BASS_RecordStart(caprate_voice, 2, BASS_SAMPLE_FLOAT, RecordingCallback_voice, 0); - if (!rchan_voice) { - printf("voice: Can't start capturing: %d\n", BASS_ErrorGetCode()); - close_audio_voice(); - ret |= 2; - } - else - { - opencapdev_voice = capdev; - setMICvolume(initialMICvol); - } - } - } - - if (ret == 0) - printf("voice started successfully for PBdev:%d and CAPdev:%d\n", openpbdev_voice, opencapdev_voice); - else - { - opencapdev_voice = -1; - openpbdev_voice = -1; - readAudioDevices(); - } - if (ret == 1) - printf("voice initialized: PBerror CapOK\n"); - if (ret == 2) - printf("voice initialized: PBOK CapERROR\n"); - if (ret == 3) - printf("voice initialized: PBerror CapERROR\n"); - -#endif - - return ret; -} - -#ifdef _LINUX_ -void selectPBdevice_voice() -{ - if (!BASS_SetDevice(openpbdev_voice)) - printf("BASS_SetDevice: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode()); -} - -void selectCAPdevice_voice() -{ - if (!BASS_SetDevice(opencapdev_voice)) - printf("BASS_SetDevice: %d err:%d\n", opencapdev_voice, BASS_ErrorGetCode()); -} - -void close_audio_voice() -{ - printf("voice: close Audio Devices\n"); - if (stream_voice > 0) - BASS_StreamFree(stream_voice); - - if (openpbdev_voice != -1) - { - selectPBdevice_voice(); - int r = BASS_Free(); - if (!r) printf("voice: Bass_Free error: %d\n", BASS_ErrorGetCode()); - } - - if (rchan_voice > 0) - BASS_ChannelStop(rchan_voice); - - if (opencapdev_voice != -1) - { - selectCAPdevice_voice(); - int rr = BASS_RecordFree(); - if (!rr) printf("voice: Bass_RecordFree error: %d\n", BASS_ErrorGetCode()); - } - - openpbdev_voice = -1; - opencapdev_voice = -1; - rchan_voice = 0; - stream_voice = 0; -} - -void setLSvolume(int v) -{ - if (v < 0 || v>100) return; - - // the volume comes in % 0..99 - // map to 0..1 - float vf = v; - vf /= 100; - - //printf("set PB volume to:%d / %f [0..1]\n", v, vf ); - - selectPBdevice_voice(); - if (!BASS_SetVolume(vf)) - printf("setPBvolume: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode()); -} - -void setMICvolume(int v) -{ - if (v < 0 || v>100) return; - - // the volume comes in % 0..99 - // map to min/maxPBvol - float vf = v; - vf /= 100; - - //printf("set CAP volume to:%d / %f [0..1]\n", v, vf); - - selectCAPdevice_voice(); - if (!BASS_RecordSetInput(-1, BASS_INPUT_ON, vf)) - { - printf("setCAPvolume: %d err:%d, using software level\n", opencapdev_voice, BASS_ErrorGetCode()); - softwareCAPvolume_voice = ((float)v / 100); - } -} - - -// capture callback -BOOL CALLBACK RecordingCallback_voice(HRECORD handle, const void* buffer, DWORD length, void* user) -{ - //printf("captured %ld samples, channels:%d\n",length/sizeof(float),2); - //measure_speed(length/sizeof(float)); - - float* fbuffer = (float*)buffer; - //showbytestringf((char*)"cap:", fbuffer, 10); - //printf("w:%ld ",length/sizeof(float)); - for (unsigned int i = 0; i < (length / sizeof(float)); i += 2) - { - //printf("%f\n",fbuffer[i]); - cap_write_fifo_voice(fbuffer[i]); - } - - return TRUE; // continue recording -} - -// play callback -// length: bytes. float=4byte, 2channels, so it requests samples*8 -DWORD CALLBACK WriteStream_voice(HSTREAM handle, float* buffer, DWORD length, void* user) -{ - //printf("requested %ld samples\n", length / sizeof(float)); - int ret = pb_read_fifo_voice(buffer, length / sizeof(float)); - if (ret == 0) - { - // fifo empty, send 00 - memset(buffer, 0, length); - } - return length; -} - -#endif - -// set volume -void setVolume_voice(int pbcap, int v) -{ - if (pbcap == 0) setLSvolume(v); - else setMICvolume(v); -} - -// ================= resampling and other tasks for voice audio ================= - -// samples come from the data-audio capture with a speed of caprate -// resample (if required) to VOICE_SAMPRATE, which is the voice-audio rate -void toVoice(float sample) -{ - if (caprate == VOICE_SAMPRATE) - { - // resampling not required, just put in LS fifo - pb_write_fifo_voice(sample); - } - else - { - pb_write_fifo_voice(sample); - // samprate of incoming signal is 44100, voice needs 48000 - // we have 44100 samples/s, so we ar missing 3900 S/s. - // if we insert an additional sample every 11 samples - // this results in a rate of 48109 S/s - static int cnt = 0; - if (++cnt >= 11) - { - cnt = 0; - pb_write_fifo_voice(sample); - } - } -} - -// ================= VOICE FIFOs =================== - -#ifdef _WIN32_ -CRITICAL_SECTION cap_crit_sec_voice; -CRITICAL_SECTION pb_crit_sec_voice; -#define CAP_LOCK_VOICE EnterCriticalSection(&cap_crit_sec_voice) -#define PB_LOCK_VOICE EnterCriticalSection(&pb_crit_sec_voice) -void CAP_UNLOCK_VOICE() -{ - if (&cap_crit_sec_voice != NULL) - LeaveCriticalSection(&cap_crit_sec_voice); -} -void PB_UNLOCK_VOICE() -{ - if (&pb_crit_sec_voice != NULL) - LeaveCriticalSection(&pb_crit_sec_voice); -} -#endif - -#ifdef _LINUX_ -pthread_mutex_t cap_crit_sec_voice; -pthread_mutex_t pb_crit_sec_voice; -#define CAP_LOCK_VOICE pthread_mutex_lock(&cap_crit_sec_voice) -void CAP_UNLOCK_VOICE() { pthread_mutex_unlock(&cap_crit_sec_voice); } -#define PB_LOCK_VOICE pthread_mutex_lock(&pb_crit_sec_voice) -void PB_UNLOCK_VOICE() { pthread_mutex_unlock(&pb_crit_sec_voice); } -#endif - -#define AUDIO_PLAYBACK_BUFLEN_VOICE (48000) -#define AUDIO_CAPTURE_BUFLEN_VOICE (48000) - -int cap_wridx_voice = 0; -int cap_rdidx_voice = 0; -float cap_buffer_voice[AUDIO_CAPTURE_BUFLEN_VOICE]; - -int pb_wridx_voice = 0; -int pb_rdidx_voice = 0; -float pb_buffer_voice[AUDIO_PLAYBACK_BUFLEN_VOICE]; - -void init_pipes_voice() -{ -#ifdef _WIN32_ - if (&cap_crit_sec_voice != NULL) DeleteCriticalSection(&cap_crit_sec_voice); - InitializeCriticalSection(&cap_crit_sec_voice); - - if (&pb_crit_sec_voice != NULL) DeleteCriticalSection(&pb_crit_sec_voice); - InitializeCriticalSection(&pb_crit_sec_voice); -#endif -} - -// write one sample into the fifo -// overwrite old data if the fifo is full -void cap_write_fifo_voice(float sample) -{ - if (((cap_wridx_voice + 1) % AUDIO_CAPTURE_BUFLEN_VOICE) == cap_rdidx_voice) - { - //printf("cap_voice fifo full\n"); - CAP_UNLOCK_VOICE(); - return; - } - - CAP_LOCK_VOICE; - cap_buffer_voice[cap_wridx_voice] = sample; - if (++cap_wridx_voice >= AUDIO_CAPTURE_BUFLEN_VOICE) cap_wridx_voice = 0; - CAP_UNLOCK_VOICE(); -} - -int cap_read_fifo_voice(float* data) -{ - CAP_LOCK_VOICE; - - if (cap_rdidx_voice == cap_wridx_voice) - { - // Fifo empty, no data available - CAP_UNLOCK_VOICE(); - return 0; - } - - *data = cap_buffer_voice[cap_rdidx_voice]; - if (++cap_rdidx_voice >= AUDIO_CAPTURE_BUFLEN_VOICE) cap_rdidx_voice = 0; - CAP_UNLOCK_VOICE(); - - return 1; -} - -void cap_write_fifo_clear_voice() -{ - cap_wridx_voice = cap_rdidx_voice = 0; -} - - -void pb_write_fifo_clear_voice() -{ - pb_wridx_voice = pb_rdidx_voice = 0; -} - -int pb_fifo_freespace_voice(int nolock) -{ - int freebuf = 0; - - if (nolock == 0) PB_LOCK_VOICE; - - int elemInFifo = (pb_wridx_voice + AUDIO_PLAYBACK_BUFLEN_VOICE - pb_rdidx_voice) % AUDIO_PLAYBACK_BUFLEN_VOICE; - freebuf = AUDIO_PLAYBACK_BUFLEN_VOICE - elemInFifo; - - if (nolock == 0) PB_UNLOCK_VOICE(); - - return freebuf; -} - -void pb_write_fifo_voice(float sample) -{ - PB_LOCK_VOICE; - - // check if there is free space in fifo - if (pb_fifo_freespace_voice(1) == 0) - { - PB_UNLOCK_VOICE(); - //printf("************* pb fifo_voice full\n"); - return; - } - - pb_buffer_voice[pb_wridx_voice] = sample; - if (++pb_wridx_voice >= AUDIO_PLAYBACK_BUFLEN_VOICE) pb_wridx_voice = 0; - PB_UNLOCK_VOICE(); -} - -int pb_fifo_usedspace_voice() -{ - int anz = pb_fifo_freespace_voice(0); - return AUDIO_PLAYBACK_BUFLEN_VOICE - anz; -} - -// read elements floats from fifo or return 0 if not enough floats are available -int pb_read_fifo_voice(float* data, int elements) -{ - //printf("pb read fifo_voice: %d\n",elements); - PB_LOCK_VOICE; - - int e = AUDIO_PLAYBACK_BUFLEN_VOICE - pb_fifo_freespace_voice(1); - if (e < elements) - { - // Fifo empty, no data available - PB_UNLOCK_VOICE(); - //printf("pb fifo empty, need:%d have:%d size:%d\n",elements,e,AUDIO_PLAYBACK_BUFLEN); - return 0; - } - - for (int i = 0; i < elements; i+=2) - { - // channel1 and the same for channel 2 - data[i] = pb_buffer_voice[pb_rdidx_voice]; - data[i+1] = pb_buffer_voice[pb_rdidx_voice]; - if (++pb_rdidx_voice >= AUDIO_PLAYBACK_BUFLEN_VOICE) pb_rdidx_voice = 0; - } - //printf("read %d floats\n",elements); - - PB_UNLOCK_VOICE(); - return 1; -} - -void clear_voice_fifos() -{ - pb_write_fifo_clear_voice(); - cap_write_fifo_clear_voice(); -} \ No newline at end of file diff --git a/hsmodem/audio_voice_wasapi.cpp b/hsmodem/audio_voice_wasapi.cpp deleted file mode 100755 index a9afafb..0000000 --- a/hsmodem/audio_voice_wasapi.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* -* High Speed modem to transfer data in a 2,7kHz SSB channel -* ========================================================= -* Author: DJ0ABR -* -* (c) DJ0ABR -* www.dj0abr.de -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* audio.c ... very similar to audio.c but is used for Microphone / Loudspeaker -* -*/ - -#include "hsmodem.h" - -void cap_write_fifo(float sample); -int pb_read_fifo(float* data, int elements); -void close_wasapi_voice(); -DWORD CALLBACK PBcallback_wasapi_voice(void* buffer, DWORD length, void* user); -DWORD CALLBACK CAPcallback_wasapi_voice(void* buffer, DWORD length, void* user); -void cap_write_fifo_voice(float sample); -int pb_read_fifo_voice(float* data, int elements); - -#define WASAPI_CHANNELS_VOICE 2 - -float minPBvol_voice = 0; -float maxPBvol_voice = 99; -float minCAPvol_voice = 0; -float maxCAPvol_voice = 99; - -extern int openpbdev_voice; -extern int opencapdev_voice; - -extern float softwareCAPvolume_voice; - -int mic_channel_num = 2; - -#ifdef _WIN32_ - -int init_wasapi_voice(int pbdev, int capdev) -{ - int ret = 0; - - close_wasapi_voice(); - - if (VoiceAudioMode == VOICEMODE_OFF) return 0; // Voice off - - // ======= init PLAYBACK device ======== - -// initialize default output device - if (!BASS_WASAPI_Init(pbdev, VOICE_SAMPRATE, WASAPI_CHANNELS_VOICE, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, PBcallback_wasapi_voice, NULL)) - { - printf("Can't initialize wasapi voice output device: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - - // read real device number since a -1 cannot be started - int device = BASS_WASAPI_GetDevice(); - if (device == -1) - { - printf("BASS_WASAPI_GetDevice_voice: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - pbdev = device; - - // read the possible volume settings - BASS_WASAPI_INFO info; - if (!BASS_WASAPI_GetInfo(&info)) - { - printf("BASS_WASAPI_GetInfo: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - minPBvol_voice = info.volmin; - maxPBvol_voice = info.volmax; - - // start playback - if (!BASS_WASAPI_Start()) - { - printf("BASS_WASAPI_Start voice: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - openpbdev_voice = pbdev; - } - } - } - - // ======= init CAPTURE device ======== - - // initalize default recording device - if (capdev == -1) capdev = -2; // cap: -2 is the default device for input - - BOOL micret = false; - mic_channel_num = 2; - micret = BASS_WASAPI_Init(capdev, VOICE_SAMPRATE, mic_channel_num, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, CAPcallback_wasapi_voice, NULL); - if (!micret) - { - micret = BASS_WASAPI_Init(capdev, VOICE_SAMPRATE, 1, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, CAPcallback_wasapi_voice, NULL); - if (!micret) - { - printf("Can't initialize wasapi voice recording device: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - mic_channel_num = 1; - } - } - - if(micret) - { - printf("mic opened with %d channels\n", mic_channel_num); - // read real device number since a -2 cannot be started - int device = BASS_WASAPI_GetDevice(); - if (device == -1) - { - printf("BASS_WASAPI_GetDevice: voice: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - capdev = device; - - // read the possible volume settings - BASS_WASAPI_INFO info; - if (!BASS_WASAPI_GetInfo(&info)) - { - printf("BASS_WASAPI_GetInfo: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - minCAPvol_voice = info.volmin; - maxCAPvol_voice = info.volmax; - - // start recording - if (!BASS_WASAPI_Start()) - { - printf("BASS_WASAPI_Start voice: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - opencapdev_voice = capdev; - } - } - } - - if (ret == 0) - printf("wasapi voice started successfully for PBdev:%d and CAPdev:%d\n", openpbdev_voice, opencapdev_voice); - else - { - opencapdev_voice = -1; - openpbdev_voice = -1; - readAudioDevices(); - } - if (ret == 1) - printf("wasapi voice initialized: PBerror CapOK\n"); - if (ret == 2) - printf("wasapi voice initialized: PBOK CapERROR\n"); - if (ret == 3) - printf("wasapi voice initialized: PBerror CapERROR\n"); - - return ret; -} - -int selectPBdevice_wasapi_voice() -{ - if (!BASS_WASAPI_SetDevice(openpbdev_voice)) - { - printf("BASS_WASAPI_SetDevice VOICE: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode()); - return 0; - } - return 1; -} - -int selectCAPdevice_wasapi_voice() -{ - if (!BASS_WASAPI_SetDevice(opencapdev_voice)) - { - printf("BASS_WASAPI_SetDevice VOICE: %d err:%d\n", opencapdev_voice, BASS_ErrorGetCode()); - return 0; - } - return 1; -} - -void close_wasapi_voice() -{ - printf("close WASAPI Voice Devices\n"); - - if (openpbdev_voice != -1) - { - if(selectPBdevice_wasapi_voice()) - if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free voice: dev:%d err:%d\n", openpbdev_voice, BASS_ErrorGetCode()); - } - - if (opencapdev_voice != -1) - { - if(selectCAPdevice_wasapi_voice()) - if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free voice: dev:%d err:%d\n", opencapdev_voice, BASS_ErrorGetCode()); - } - printf("closed WASAPI Voice Devices\n"); -} - -void setLSvolume(int v) -{ - // the volume comes in % 0..99 - // map to min/maxPBvol - float vf = v * (maxPBvol_voice - minPBvol_voice) / 100 + minPBvol_voice; - - if (vf < minPBvol_voice) vf = minPBvol_voice; - if (vf > maxPBvol_voice) vf = maxPBvol_voice; - - //printf("set PB volume to:%d / %f [%f..%f]\n", v, vf, minPBvol_voice, maxPBvol_voice); - - if(selectPBdevice_wasapi_voice()) - if (!BASS_WASAPI_SetVolume(BASS_WASAPI_CURVE_DB, vf)) - printf("setPBvolume: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode()); -} - -void setMICvolume(int v) -{ - // non of the BASS input level functions are working in WASAPI exclusive mode - // so we adjust the input level by software - softwareCAPvolume_voice = (float)v; - softwareCAPvolume_voice /= 50; -} - -DWORD CALLBACK PBcallback_wasapi_voice(void* buffer, DWORD length, void* user) -{ - float* fbuffer = (float*)buffer; - int ret = pb_read_fifo_voice(fbuffer, length / sizeof(float)); - if (ret == 0) - { - // fifo empty, send 00 - memset(buffer, 0, length); - } - return length; -} - -DWORD CALLBACK CAPcallback_wasapi_voice(void* buffer, DWORD length, void* user) -{ - float* fbuffer = (float*)buffer; - for (unsigned int i = 0; i < (length / sizeof(float)); i += mic_channel_num) - { - cap_write_fifo_voice(fbuffer[i]); - } - - return TRUE; // continue recording -} - -#endif diff --git a/hsmodem/audio_wasapi.cpp b/hsmodem/audio_wasapi.cpp deleted file mode 100755 index f3c81f3..0000000 --- a/hsmodem/audio_wasapi.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* -* High Speed modem to transfer data in a 2,7kHz SSB channel -* ========================================================= -* Author: DJ0ABR -* -* (c) DJ0ABR -* www.dj0abr.de -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* audio_wasabi.c ... functions to handle audio in/out via a soundcard uses the "BASSWASAPI" library -* wasapi is needed because we need exclusive access to the sound card which is not provided for Windows with the normal bass.lib -*/ - -#include "hsmodem.h" - -#ifdef _WIN32_ - -#define WASAPI_CHANNELS 2 // wasapi works with 2 only - -void cap_write_fifo(float sample); -int pb_read_fifo(float* data, int elements); -void close_wasapi(); -DWORD CALLBACK PBcallback_wasapi(void* buffer, DWORD length, void* user); -DWORD CALLBACK CAPcallback_wasapi(void* buffer, DWORD length, void* user); - -float minPBvol = 0; -float maxPBvol = 99; -float minCAPvol = 0; -float maxCAPvol = 99; - -extern int openpbdev; -extern int opencapdev; - -int init_wasapi(int pbdev, int capdev) -{ - int ret = 0; - - close_wasapi(); - - // ======= init PLAYBACK device ======== - - // initialize default output device - if (!BASS_WASAPI_Init(pbdev, caprate, WASAPI_CHANNELS, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, PBcallback_wasapi, NULL)) - { - printf("Can't initialize output device: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - - // read real device number since a -1 cannot be started - int device = BASS_WASAPI_GetDevice(); - if (device == -1) - { - printf("BASS_WASAPI_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - pbdev = device; - - // read the possible volume settings - BASS_WASAPI_INFO info; - if (!BASS_WASAPI_GetInfo(&info)) - { - printf("BASS_WASAPI_GetInfo: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - { - minPBvol = info.volmin; - maxPBvol = info.volmax; - - // start playback - if (!BASS_WASAPI_Start()) - { - printf("BASS_WASAPI_Start: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret = 1; - } - else - openpbdev = pbdev; - } - } - } - - // ======= init CAPTURE device ======== - - // initalize default recording device - if (capdev == -1) capdev = -2; // cap: -2 is the default device for input - if (!BASS_WASAPI_Init(capdev, caprate, WASAPI_CHANNELS, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, CAPcallback_wasapi, NULL)) - { - printf("Can't initialize recording device: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - - // read real device number since a -2 cannot be started - int device = BASS_WASAPI_GetDevice(); - if (device == -1) - { - printf("BASS_WASAPI_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - capdev = device; - - // read the possible volume settings - BASS_WASAPI_INFO info; - if (!BASS_WASAPI_GetInfo(&info)) - { - printf("BASS_WASAPI_GetInfo: %d err:%d\n", pbdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - { - minCAPvol = info.volmin; - maxCAPvol = info.volmax; - - // start recording - if (!BASS_WASAPI_Start()) - { - printf("BASS_WASAPI_Start: %d err:%d\n", capdev, BASS_ErrorGetCode()); - ret |= 2; - } - else - opencapdev = capdev; - } - } - } - - if (ret == 0) - printf("WASAPI started successfully for PBdev:%d and CAPdev:%d\n", openpbdev, opencapdev); - else - { - opencapdev = -1; - openpbdev = -1; - readAudioDevices(); - } - if (ret == 1) - printf("wasapi audio initialized: PBerror CapOK\n"); - if (ret == 2) - printf("wasapi audio initialized: PBOK CapERROR\n"); - if (ret == 3) - printf("wasapi audio initialized: PBerror CapERROR\n"); - - return ret; -} - -int selectPBdevice_wasapi() -{ - if (!BASS_WASAPI_SetDevice(openpbdev)) - { - printf("BASS_WASAPI_SetDevice: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); - return 0; - } - return 1; -} - -int selectCAPdevice_wasapi() -{ - if (!BASS_WASAPI_SetDevice(opencapdev)) - { - printf("BASS_WASAPI_SetDevice: %d err:%d\n", opencapdev, BASS_ErrorGetCode()); - return 0; - } - return 1; -} - -void setPBvolume(int v) -{ - // the volume comes in % 0..99 - // map to min/maxPBvol - float vf = v * (maxPBvol - minPBvol) / 100 + minPBvol; - - if (vf < minPBvol) vf = minPBvol; - if (vf > maxPBvol) vf = maxPBvol; - - //printf("set PB volume to:%d / %f [%f..%f]\n", v, vf, minPBvol, maxPBvol); - - if(selectPBdevice_wasapi()) - if (!BASS_WASAPI_SetVolume(BASS_WASAPI_CURVE_DB, vf)) - printf("setPBvolume: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); -} - -void setCAPvolume(int v) -{ - // non of the BASS input level functions are working in WASAPI exclusive mode - // so we adjust the input level by software - softwareCAPvolume = (float)v; - softwareCAPvolume /= 50; -} - -void close_wasapi() -{ - printf("close WASAPI Audio Devices\n"); - - if (openpbdev != -1) - { - if(selectPBdevice_wasapi()) - if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free: dev:%d err:%d\n", openpbdev, BASS_ErrorGetCode()); - } - - if (opencapdev != -1) - { - if(selectCAPdevice_wasapi()) - if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free: dev:%d err:%d\n", opencapdev, BASS_ErrorGetCode()); - } -} - -DWORD CALLBACK PBcallback_wasapi(void* buffer, DWORD length, void* user) -{ - float* fbuffer = (float*)buffer; - - // requested number of stereo samples: length/sizeof(float) - // requested real number of samples - int req_samples = length / sizeof(float) / WASAPI_CHANNELS; - // prepare a buffer to store the mono samples from the fifo - float* fdata = (float*)malloc(sizeof(float) * req_samples); - // read mono samples from fifo - int ret = pb_read_fifo(fdata, req_samples); - if (ret == 0) - { - // fifo empty, send 00 - memset(fdata, 0, sizeof(float) * req_samples); - } - // copy the mono samples into the stereo output buffer - int didx = 0; - for (int i = 0; i < req_samples; i++) - { - fbuffer[didx++] = fdata[i]; - fbuffer[didx++] = fdata[i]; - } - - free(fdata); - return length; -} - -DWORD CALLBACK CAPcallback_wasapi(void* buffer, DWORD length, void* user) -{ - //printf("CAP callback, len:%d\n",length); - //measure_speed_bps(length/sizeof(float)/ WASAPI_CHANNELS); - - float* fbuffer = (float*)buffer; - //showbytestringf((char*)"rx: ", fbuffer, 10); - //printf("%10.6f\n", fbuffer[0]); - for (unsigned int i = 0; i < (length / sizeof(float)); i += WASAPI_CHANNELS) - { - //nullChecker(fbuffer[i],fbuffer, length / sizeof(float)); - cap_write_fifo(fbuffer[i]); - } - - return TRUE; // continue recording -} - -#endif // _WIN32_ diff --git a/hsmodem/bass.h b/hsmodem/bass.h deleted file mode 100755 index e6f2416..0000000 --- a/hsmodem/bass.h +++ /dev/null @@ -1,1160 +0,0 @@ -/* - BASS 2.4 C/C++ header file - Copyright (c) 1999-2019 Un4seen Developments Ltd. - - See the BASS.CHM file for more detailed documentation -*/ - -#ifndef BASS_H -#define BASS_H - -#ifdef _WIN32 -#include -typedef unsigned __int64 QWORD; -#else -#include -#define WINAPI -#define CALLBACK -typedef uint8_t BYTE; -typedef uint16_t WORD; -typedef uint32_t DWORD; -typedef uint64_t QWORD; -#ifdef __OBJC__ -#include -#else -typedef int BOOL; -#endif -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif -#define LOBYTE(a) (BYTE)(a) -#define HIBYTE(a) (BYTE)((a)>>8) -#define LOWORD(a) (WORD)(a) -#define HIWORD(a) (WORD)((a)>>16) -#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8)) -#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16)) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define BASSVERSION 0x204 // API version -#define BASSVERSIONTEXT "2.4" - -#ifndef BASSDEF -#define BASSDEF(f) WINAPI f -#else -#define NOBASSOVERLOADS -#endif - -typedef DWORD HMUSIC; // MOD music handle -typedef DWORD HSAMPLE; // sample handle -typedef DWORD HCHANNEL; // playing sample's channel handle -typedef DWORD HSTREAM; // sample stream handle -typedef DWORD HRECORD; // recording handle -typedef DWORD HSYNC; // synchronizer handle -typedef DWORD HDSP; // DSP handle -typedef DWORD HFX; // DX8 effect handle -typedef DWORD HPLUGIN; // Plugin handle - -// Error codes returned by BASS_ErrorGetCode -#define BASS_OK 0 // all is OK -#define BASS_ERROR_MEM 1 // memory error -#define BASS_ERROR_FILEOPEN 2 // can't open the file -#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver -#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost -#define BASS_ERROR_HANDLE 5 // invalid handle -#define BASS_ERROR_FORMAT 6 // unsupported sample format -#define BASS_ERROR_POSITION 7 // invalid position -#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called -#define BASS_ERROR_START 9 // BASS_Start has not been successfully called -#define BASS_ERROR_SSL 10 // SSL/HTTPS support isn't available -#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever -#define BASS_ERROR_NOTAUDIO 17 // file does not contain audio -#define BASS_ERROR_NOCHAN 18 // can't get a free channel -#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified -#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified -#define BASS_ERROR_NO3D 21 // no 3D support -#define BASS_ERROR_NOEAX 22 // no EAX support -#define BASS_ERROR_DEVICE 23 // illegal device number -#define BASS_ERROR_NOPLAY 24 // not playing -#define BASS_ERROR_FREQ 25 // illegal sample rate -#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream -#define BASS_ERROR_NOHW 29 // no hardware voices available -#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data -#define BASS_ERROR_NONET 32 // no internet connection could be opened -#define BASS_ERROR_CREATE 33 // couldn't create the file -#define BASS_ERROR_NOFX 34 // effects are not available -#define BASS_ERROR_NOTAVAIL 37 // requested data/action is not available -#define BASS_ERROR_DECODE 38 // the channel is/isn't a "decoding channel" -#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed -#define BASS_ERROR_TIMEOUT 40 // connection timedout -#define BASS_ERROR_FILEFORM 41 // unsupported file format -#define BASS_ERROR_SPEAKER 42 // unavailable speaker -#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons) -#define BASS_ERROR_CODEC 44 // codec is not available/supported -#define BASS_ERROR_ENDED 45 // the channel/file has ended -#define BASS_ERROR_BUSY 46 // the device is busy -#define BASS_ERROR_UNSTREAMABLE 47 // unstreamable file -#define BASS_ERROR_UNKNOWN -1 // some other mystery problem - -// BASS_SetConfig options -#define BASS_CONFIG_BUFFER 0 -#define BASS_CONFIG_UPDATEPERIOD 1 -#define BASS_CONFIG_GVOL_SAMPLE 4 -#define BASS_CONFIG_GVOL_STREAM 5 -#define BASS_CONFIG_GVOL_MUSIC 6 -#define BASS_CONFIG_CURVE_VOL 7 -#define BASS_CONFIG_CURVE_PAN 8 -#define BASS_CONFIG_FLOATDSP 9 -#define BASS_CONFIG_3DALGORITHM 10 -#define BASS_CONFIG_NET_TIMEOUT 11 -#define BASS_CONFIG_NET_BUFFER 12 -#define BASS_CONFIG_PAUSE_NOPLAY 13 -#define BASS_CONFIG_NET_PREBUF 15 -#define BASS_CONFIG_NET_PASSIVE 18 -#define BASS_CONFIG_REC_BUFFER 19 -#define BASS_CONFIG_NET_PLAYLIST 21 -#define BASS_CONFIG_MUSIC_VIRTUAL 22 -#define BASS_CONFIG_VERIFY 23 -#define BASS_CONFIG_UPDATETHREADS 24 -#define BASS_CONFIG_DEV_BUFFER 27 -#define BASS_CONFIG_REC_LOOPBACK 28 -#define BASS_CONFIG_VISTA_TRUEPOS 30 -#define BASS_CONFIG_IOS_SESSION 34 -#define BASS_CONFIG_IOS_MIXAUDIO 34 -#define BASS_CONFIG_DEV_DEFAULT 36 -#define BASS_CONFIG_NET_READTIMEOUT 37 -#define BASS_CONFIG_VISTA_SPEAKERS 38 -#define BASS_CONFIG_IOS_SPEAKER 39 -#define BASS_CONFIG_MF_DISABLE 40 -#define BASS_CONFIG_HANDLES 41 -#define BASS_CONFIG_UNICODE 42 -#define BASS_CONFIG_SRC 43 -#define BASS_CONFIG_SRC_SAMPLE 44 -#define BASS_CONFIG_ASYNCFILE_BUFFER 45 -#define BASS_CONFIG_OGG_PRESCAN 47 -#define BASS_CONFIG_MF_VIDEO 48 -#define BASS_CONFIG_AIRPLAY 49 -#define BASS_CONFIG_DEV_NONSTOP 50 -#define BASS_CONFIG_IOS_NOCATEGORY 51 -#define BASS_CONFIG_VERIFY_NET 52 -#define BASS_CONFIG_DEV_PERIOD 53 -#define BASS_CONFIG_FLOAT 54 -#define BASS_CONFIG_NET_SEEK 56 -#define BASS_CONFIG_AM_DISABLE 58 -#define BASS_CONFIG_NET_PLAYLIST_DEPTH 59 -#define BASS_CONFIG_NET_PREBUF_WAIT 60 -#define BASS_CONFIG_ANDROID_SESSIONID 62 -#define BASS_CONFIG_WASAPI_PERSIST 65 -#define BASS_CONFIG_REC_WASAPI 66 -#define BASS_CONFIG_ANDROID_AAUDIO 67 - -// BASS_SetConfigPtr options -#define BASS_CONFIG_NET_AGENT 16 -#define BASS_CONFIG_NET_PROXY 17 -#define BASS_CONFIG_IOS_NOTIFY 46 -#define BASS_CONFIG_LIBSSL 64 - -// BASS_CONFIG_IOS_SESSION flags -#define BASS_IOS_SESSION_MIX 1 -#define BASS_IOS_SESSION_DUCK 2 -#define BASS_IOS_SESSION_AMBIENT 4 -#define BASS_IOS_SESSION_SPEAKER 8 -#define BASS_IOS_SESSION_DISABLE 16 - -// BASS_Init flags -#define BASS_DEVICE_8BITS 1 // 8 bit -#define BASS_DEVICE_MONO 2 // mono -#define BASS_DEVICE_3D 4 // enable 3D functionality -#define BASS_DEVICE_16BITS 8 // limit output to 16 bit -#define BASS_DEVICE_LATENCY 0x100 // calculate device latency (BASS_INFO struct) -#define BASS_DEVICE_CPSPEAKERS 0x400 // detect speakers via Windows control panel -#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment -#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement -#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin -#define BASS_DEVICE_FREQ 0x4000 // set device sample rate -#define BASS_DEVICE_STEREO 0x8000 // limit output to stereo -#define BASS_DEVICE_HOG 0x10000 // hog/exclusive mode -#define BASS_DEVICE_AUDIOTRACK 0x20000 // use AudioTrack output -#define BASS_DEVICE_DSOUND 0x40000 // use DirectSound output - -// DirectSound interfaces (for use with BASS_GetDSoundObject) -#define BASS_OBJECT_DS 1 // IDirectSound -#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener - -// Device info structure -typedef struct { -#if defined(_WIN32_WCE) || (WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) - const wchar_t *name; // description - const wchar_t *driver; // driver -#else - const char *name; // description - const char *driver; // driver -#endif - DWORD flags; -} BASS_DEVICEINFO; - -// BASS_DEVICEINFO flags -#define BASS_DEVICE_ENABLED 1 -#define BASS_DEVICE_DEFAULT 2 -#define BASS_DEVICE_INIT 4 -#define BASS_DEVICE_LOOPBACK 8 - -#define BASS_DEVICE_TYPE_MASK 0xff000000 -#define BASS_DEVICE_TYPE_NETWORK 0x01000000 -#define BASS_DEVICE_TYPE_SPEAKERS 0x02000000 -#define BASS_DEVICE_TYPE_LINE 0x03000000 -#define BASS_DEVICE_TYPE_HEADPHONES 0x04000000 -#define BASS_DEVICE_TYPE_MICROPHONE 0x05000000 -#define BASS_DEVICE_TYPE_HEADSET 0x06000000 -#define BASS_DEVICE_TYPE_HANDSET 0x07000000 -#define BASS_DEVICE_TYPE_DIGITAL 0x08000000 -#define BASS_DEVICE_TYPE_SPDIF 0x09000000 -#define BASS_DEVICE_TYPE_HDMI 0x0a000000 -#define BASS_DEVICE_TYPE_DISPLAYPORT 0x40000000 - -// BASS_GetDeviceInfo flags -#define BASS_DEVICES_AIRPLAY 0x1000000 - -typedef struct { - DWORD flags; // device capabilities (DSCAPS_xxx flags) - DWORD hwsize; // size of total device hardware memory - DWORD hwfree; // size of free device hardware memory - DWORD freesam; // number of free sample slots in the hardware - DWORD free3d; // number of free 3D sample slots in the hardware - DWORD minrate; // min sample rate supported by the hardware - DWORD maxrate; // max sample rate supported by the hardware - BOOL eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used) - DWORD minbuf; // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY) - DWORD dsver; // DirectSound version - DWORD latency; // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY) - DWORD initflags; // BASS_Init "flags" parameter - DWORD speakers; // number of speakers available - DWORD freq; // current output rate -} BASS_INFO; - -// BASS_INFO flags (from DSOUND.H) -#define DSCAPS_CONTINUOUSRATE 0x00000010 // supports all sample rates between min/maxrate -#define DSCAPS_EMULDRIVER 0x00000020 // device does NOT have hardware DirectSound support -#define DSCAPS_CERTIFIED 0x00000040 // device driver has been certified by Microsoft -#define DSCAPS_SECONDARYMONO 0x00000100 // mono -#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo -#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit -#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit - -// Recording device info structure -typedef struct { - DWORD flags; // device capabilities (DSCCAPS_xxx flags) - DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags) - DWORD inputs; // number of inputs - BOOL singlein; // TRUE = only 1 input can be set at a time - DWORD freq; // current input rate -} BASS_RECORDINFO; - -// BASS_RECORDINFO flags (from DSOUND.H) -#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording support -#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED // device driver has been certified by Microsoft - -// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H) -#ifndef WAVE_FORMAT_1M08 -#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ -#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ -#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ -#endif - -// Sample info structure -typedef struct { - DWORD freq; // default playback rate - float volume; // default volume (0-1) - float pan; // default pan (-1=left, 0=middle, 1=right) - DWORD flags; // BASS_SAMPLE_xxx flags - DWORD length; // length (in bytes) - DWORD max; // maximum simultaneous playbacks - DWORD origres; // original resolution - DWORD chans; // number of channels - DWORD mingap; // minimum gap (ms) between creating channels - DWORD mode3d; // BASS_3DMODE_xxx mode - float mindist; // minimum distance - float maxdist; // maximum distance - DWORD iangle; // angle of inside projection cone - DWORD oangle; // angle of outside projection cone - float outvol; // delta-volume outside the projection cone - DWORD vam; // voice allocation/management flags (BASS_VAM_xxx) - DWORD priority; // priority (0=lowest, 0xffffffff=highest) -} BASS_SAMPLE; - -#define BASS_SAMPLE_8BITS 1 // 8 bit -#define BASS_SAMPLE_FLOAT 256 // 32 bit floating-point -#define BASS_SAMPLE_MONO 2 // mono -#define BASS_SAMPLE_LOOP 4 // looped -#define BASS_SAMPLE_3D 8 // 3D functionality -#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing -#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only) -#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management -#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects -#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume -#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing -#define BASS_SAMPLE_OVER_DIST 0x30000 // override furthest from listener (3D only) - -#define BASS_STREAM_PRESCAN 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1) -#define BASS_STREAM_AUTOFREE 0x40000 // automatically free the stream when it stop/ends -#define BASS_STREAM_RESTRATE 0x80000 // restrict the download rate of internet file streams -#define BASS_STREAM_BLOCK 0x100000 // download/play internet file stream in small blocks -#define BASS_STREAM_DECODE 0x200000 // don't play the stream, only decode (BASS_ChannelGetData) -#define BASS_STREAM_STATUS 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC - -#define BASS_MP3_IGNOREDELAY 0x200 // ignore LAME/Xing/VBRI/iTunes delay & padding info -#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN - -#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT -#define BASS_MUSIC_MONO BASS_SAMPLE_MONO -#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP -#define BASS_MUSIC_3D BASS_SAMPLE_3D -#define BASS_MUSIC_FX BASS_SAMPLE_FX -#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE -#define BASS_MUSIC_DECODE BASS_STREAM_DECODE -#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length -#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN -#define BASS_MUSIC_RAMP 0x200 // normal ramping -#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping -#define BASS_MUSIC_SURROUND 0x800 // surround sound -#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2) -#define BASS_MUSIC_FT2PAN 0x2000 // apply FastTracker 2 panning to XM files -#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does -#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does -#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing -#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing -#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position -#define BASS_MUSIC_POSRESETEX 0x400000 // stop all notes and reset bmp/etc when moving position -#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect -#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples - -// Speaker assignment flags -#define BASS_SPEAKER_FRONT 0x1000000 // front speakers -#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers -#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1) -#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1) -#define BASS_SPEAKER_N(n) ((n)<<24) // n'th pair of speakers (max 15) -#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left -#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right -#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2|BASS_SPEAKER_RIGHT - -#define BASS_ASYNCFILE 0x40000000 -#define BASS_UNICODE 0x80000000 - -#define BASS_RECORD_PAUSE 0x8000 // start recording paused -#define BASS_RECORD_ECHOCANCEL 0x2000 -#define BASS_RECORD_AGC 0x4000 - -// DX7 voice allocation & management flags -#define BASS_VAM_HARDWARE 1 -#define BASS_VAM_SOFTWARE 2 -#define BASS_VAM_TERM_TIME 4 -#define BASS_VAM_TERM_DIST 8 -#define BASS_VAM_TERM_PRIO 16 - -// Channel info structure -typedef struct { - DWORD freq; // default playback rate - DWORD chans; // channels - DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags - DWORD ctype; // type of channel - DWORD origres; // original resolution - HPLUGIN plugin; // plugin - HSAMPLE sample; // sample - const char *filename; // filename -} BASS_CHANNELINFO; - -#define BASS_ORIGRES_FLOAT 0x10000 - -// BASS_CHANNELINFO types -#define BASS_CTYPE_SAMPLE 1 -#define BASS_CTYPE_RECORD 2 -#define BASS_CTYPE_STREAM 0x10000 -#define BASS_CTYPE_STREAM_VORBIS 0x10002 -#define BASS_CTYPE_STREAM_OGG 0x10002 -#define BASS_CTYPE_STREAM_MP1 0x10003 -#define BASS_CTYPE_STREAM_MP2 0x10004 -#define BASS_CTYPE_STREAM_MP3 0x10005 -#define BASS_CTYPE_STREAM_AIFF 0x10006 -#define BASS_CTYPE_STREAM_CA 0x10007 -#define BASS_CTYPE_STREAM_MF 0x10008 -#define BASS_CTYPE_STREAM_AM 0x10009 -#define BASS_CTYPE_STREAM_DUMMY 0x18000 -#define BASS_CTYPE_STREAM_DEVICE 0x18001 -#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec -#define BASS_CTYPE_STREAM_WAV_PCM 0x50001 -#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003 -#define BASS_CTYPE_MUSIC_MOD 0x20000 -#define BASS_CTYPE_MUSIC_MTM 0x20001 -#define BASS_CTYPE_MUSIC_S3M 0x20002 -#define BASS_CTYPE_MUSIC_XM 0x20003 -#define BASS_CTYPE_MUSIC_IT 0x20004 -#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag - -typedef struct { - DWORD ctype; // channel type -#if defined(_WIN32_WCE) || (WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) - const wchar_t *name; // format description - const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...) -#else - const char *name; // format description - const char *exts; // file extension filter (*.ext1;*.ext2;etc...) -#endif -} BASS_PLUGINFORM; - -typedef struct { - DWORD version; // version (same form as BASS_GetVersion) - DWORD formatc; // number of formats - const BASS_PLUGINFORM *formats; // the array of formats -} BASS_PLUGININFO; - -// 3D vector (for 3D positions/velocities/orientations) -typedef struct BASS_3DVECTOR { -#ifdef __cplusplus - BASS_3DVECTOR() {}; - BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}; -#endif - float x; // +=right, -=left - float y; // +=up, -=down - float z; // +=front, -=behind -} BASS_3DVECTOR; - -// 3D channel modes -#define BASS_3DMODE_NORMAL 0 // normal 3D processing -#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener -#define BASS_3DMODE_OFF 2 // no 3D processing - -// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM) -#define BASS_3DALG_DEFAULT 0 -#define BASS_3DALG_OFF 1 -#define BASS_3DALG_FULL 2 -#define BASS_3DALG_LIGHT 3 - -// EAX environments, use with BASS_SetEAXParameters -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT // total number of environments -}; - -// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx) -#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F -#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F -#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F -#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F -#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F -#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F -#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F -#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F -#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F -#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F -#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F -#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F -#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F -#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F -#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F -#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F -#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F -#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F -#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F -#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F -#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F -#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F -#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F -#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F -#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F -#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F - -typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user); -/* User stream callback function. -handle : The stream that needs writing -buffer : Buffer to write the samples in -length : Number of bytes to write -user : The 'user' parameter value given when calling BASS_StreamCreate -RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end the stream. */ - -#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag - -// special STREAMPROCs -#define STREAMPROC_DUMMY (STREAMPROC*)0 // "dummy" stream -#define STREAMPROC_PUSH (STREAMPROC*)-1 // push stream -#define STREAMPROC_DEVICE (STREAMPROC*)-2 // device mix stream -#define STREAMPROC_DEVICE_3D (STREAMPROC*)-3 // device 3D mix stream - -// BASS_StreamCreateFileUser file systems -#define STREAMFILE_NOBUFFER 0 -#define STREAMFILE_BUFFER 1 -#define STREAMFILE_BUFFERPUSH 2 - -// User file stream callback functions -typedef void (CALLBACK FILECLOSEPROC)(void *user); -typedef QWORD (CALLBACK FILELENPROC)(void *user); -typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user); -typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user); - -typedef struct { - FILECLOSEPROC *close; - FILELENPROC *length; - FILEREADPROC *read; - FILESEEKPROC *seek; -} BASS_FILEPROCS; - -// BASS_StreamPutFileData options -#define BASS_FILEDATA_END 0 // end & close the file - -// BASS_StreamGetFilePosition modes -#define BASS_FILEPOS_CURRENT 0 -#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT -#define BASS_FILEPOS_DOWNLOAD 1 -#define BASS_FILEPOS_END 2 -#define BASS_FILEPOS_START 3 -#define BASS_FILEPOS_CONNECTED 4 -#define BASS_FILEPOS_BUFFER 5 -#define BASS_FILEPOS_SOCKET 6 -#define BASS_FILEPOS_ASYNCBUF 7 -#define BASS_FILEPOS_SIZE 8 -#define BASS_FILEPOS_BUFFERING 9 - -typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user); -/* Internet stream download callback function. -buffer : Buffer containing the downloaded data... NULL=end of download -length : Number of bytes in the buffer -user : The 'user' parameter value given when calling BASS_StreamCreateURL */ - -// BASS_ChannelSetSync types -#define BASS_SYNC_POS 0 -#define BASS_SYNC_END 2 -#define BASS_SYNC_META 4 -#define BASS_SYNC_SLIDE 5 -#define BASS_SYNC_STALL 6 -#define BASS_SYNC_DOWNLOAD 7 -#define BASS_SYNC_FREE 8 -#define BASS_SYNC_SETPOS 11 -#define BASS_SYNC_MUSICPOS 10 -#define BASS_SYNC_MUSICINST 1 -#define BASS_SYNC_MUSICFX 3 -#define BASS_SYNC_OGG_CHANGE 12 -#define BASS_SYNC_DEV_FAIL 14 -#define BASS_SYNC_DEV_FORMAT 15 -#define BASS_SYNC_THREAD 0x20000000 // flag: call sync in other thread -#define BASS_SYNC_MIXTIME 0x40000000 // flag: sync at mixtime, else at playtime -#define BASS_SYNC_ONETIME 0x80000000 // flag: sync only once, else continuously - -typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user); -/* Sync callback function. -handle : The sync that has occured -channel: Channel that the sync occured in -data : Additional data associated with the sync's occurance -user : The 'user' parameter given when calling BASS_ChannelSetSync */ - -typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user); -/* DSP callback function. -handle : The DSP handle -channel: Channel that the DSP is being applied to -buffer : Buffer to apply the DSP to -length : Number of bytes in the buffer -user : The 'user' parameter given when calling BASS_ChannelSetDSP */ - -typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user); -/* Recording callback function. -handle : The recording handle -buffer : Buffer containing the recorded sample data -length : Number of bytes -user : The 'user' parameter value given when calling BASS_RecordStart -RETURN : TRUE = continue recording, FALSE = stop */ - -// BASS_ChannelIsActive return values -#define BASS_ACTIVE_STOPPED 0 -#define BASS_ACTIVE_PLAYING 1 -#define BASS_ACTIVE_STALLED 2 -#define BASS_ACTIVE_PAUSED 3 -#define BASS_ACTIVE_PAUSED_DEVICE 4 - -// Channel attributes -#define BASS_ATTRIB_FREQ 1 -#define BASS_ATTRIB_VOL 2 -#define BASS_ATTRIB_PAN 3 -#define BASS_ATTRIB_EAXMIX 4 -#define BASS_ATTRIB_NOBUFFER 5 -#define BASS_ATTRIB_VBR 6 -#define BASS_ATTRIB_CPU 7 -#define BASS_ATTRIB_SRC 8 -#define BASS_ATTRIB_NET_RESUME 9 -#define BASS_ATTRIB_SCANINFO 10 -#define BASS_ATTRIB_NORAMP 11 -#define BASS_ATTRIB_BITRATE 12 -#define BASS_ATTRIB_BUFFER 13 -#define BASS_ATTRIB_GRANULE 14 -#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100 -#define BASS_ATTRIB_MUSIC_PANSEP 0x101 -#define BASS_ATTRIB_MUSIC_PSCALER 0x102 -#define BASS_ATTRIB_MUSIC_BPM 0x103 -#define BASS_ATTRIB_MUSIC_SPEED 0x104 -#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105 -#define BASS_ATTRIB_MUSIC_ACTIVE 0x106 -#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel # -#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument # - -// BASS_ChannelSlideAttribute flags -#define BASS_SLIDE_LOG 0x1000000 - -// BASS_ChannelGetData flags -#define BASS_DATA_AVAILABLE 0 // query how much data is buffered -#define BASS_DATA_FIXED 0x20000000 // flag: return 8.24 fixed-point data -#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data -#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT -#define BASS_DATA_FFT512 0x80000001 // 512 FFT -#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT -#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT -#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT -#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT -#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT -#define BASS_DATA_FFT32768 0x80000007 // 32768 FFT -#define BASS_DATA_FFT_INDIVIDUAL 0x10 // FFT flag: FFT for each channel, else all combined -#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window -#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias -#define BASS_DATA_FFT_COMPLEX 0x80 // FFT flag: return complex data -#define BASS_DATA_FFT_NYQUIST 0x100 // FFT flag: return extra Nyquist value - -// BASS_ChannelGetLevelEx flags -#define BASS_LEVEL_MONO 1 -#define BASS_LEVEL_STEREO 2 -#define BASS_LEVEL_RMS 4 -#define BASS_LEVEL_VOLPAN 8 - -// BASS_ChannelGetTags types : what's returned -#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure -#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block -#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings -#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings -#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings -#define BASS_TAG_META 5 // ICY metadata : ANSI string -#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings -#define BASS_TAG_MP4 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings -#define BASS_TAG_WMA 8 // WMA tags : series of null-terminated UTF-8 strings -#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string -#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string -#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure -#define BASS_TAG_MF 13 // Media Foundation tags : series of null-terminated UTF-8 strings -#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure -#define BASS_TAG_AM_MIME 15 // Android Media MIME type : ASCII string -#define BASS_TAG_AM_NAME 16 // Android Media codec name : ASCII string -#define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings -#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure -#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure -#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string -#define BASS_TAG_RIFF_CUE 0x104 // RIFF "cue " chunk : TAG_CUE structure -#define BASS_TAG_RIFF_SMPL 0x105 // RIFF "smpl" chunk : TAG_SMPL structure -#define BASS_TAG_APE_BINARY 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure -#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string -#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string -#define BASS_TAG_MUSIC_ORDERS 0x10002 // MOD order list : BYTE array of pattern numbers -#define BASS_TAG_MUSIC_AUTH 0x10003 // MOD author : UTF-8 string -#define BASS_TAG_MUSIC_INST 0x10100 // + instrument #, MOD instrument name : ANSI string -#define BASS_TAG_MUSIC_SAMPLE 0x10300 // + sample #, MOD sample name : ANSI string - -// ID3v1 tag structure -typedef struct { - char id[3]; - char title[30]; - char artist[30]; - char album[30]; - char year[4]; - char comment[30]; - BYTE genre; -} TAG_ID3; - -// Binary APE tag structure -typedef struct { - const char *key; - const void *data; - DWORD length; -} TAG_APE_BINARY; - -// BWF "bext" tag structure -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4200) -#endif -#pragma pack(push,1) -typedef struct { - char Description[256]; // description - char Originator[32]; // name of the originator - char OriginatorReference[32]; // reference of the originator - char OriginationDate[10]; // date of creation (yyyy-mm-dd) - char OriginationTime[8]; // time of creation (hh-mm-ss) - QWORD TimeReference; // first sample count since midnight (little-endian) - WORD Version; // BWF version (little-endian) - BYTE UMID[64]; // SMPTE UMID - BYTE Reserved[190]; -#if defined(__GNUC__) && __GNUC__<3 - char CodingHistory[0]; // history -#elif 1 // change to 0 if compiler fails the following line - char CodingHistory[]; // history -#else - char CodingHistory[1]; // history -#endif -} TAG_BEXT; -#pragma pack(pop) - -// BWF "cart" tag structures -typedef struct -{ - DWORD dwUsage; // FOURCC timer usage ID - DWORD dwValue; // timer value in samples from head -} TAG_CART_TIMER; - -typedef struct -{ - char Version[4]; // version of the data structure - char Title[64]; // title of cart audio sequence - char Artist[64]; // artist or creator name - char CutID[64]; // cut number identification - char ClientID[64]; // client identification - char Category[64]; // category ID, PSA, NEWS, etc - char Classification[64]; // classification or auxiliary key - char OutCue[64]; // out cue text - char StartDate[10]; // yyyy-mm-dd - char StartTime[8]; // hh:mm:ss - char EndDate[10]; // yyyy-mm-dd - char EndTime[8]; // hh:mm:ss - char ProducerAppID[64]; // name of vendor or application - char ProducerAppVersion[64]; // version of producer application - char UserDef[64]; // user defined text - DWORD dwLevelReference; // sample value for 0 dB reference - TAG_CART_TIMER PostTimer[8]; // 8 time markers after head - char Reserved[276]; - char URL[1024]; // uniform resource locator -#if defined(__GNUC__) && __GNUC__<3 - char TagText[0]; // free form text for scripts or tags -#elif 1 // change to 0 if compiler fails the following line - char TagText[]; // free form text for scripts or tags -#else - char TagText[1]; // free form text for scripts or tags -#endif -} TAG_CART; - -// RIFF "cue " tag structures -typedef struct -{ - DWORD dwName; - DWORD dwPosition; - DWORD fccChunk; - DWORD dwChunkStart; - DWORD dwBlockStart; - DWORD dwSampleOffset; -} TAG_CUE_POINT; - -typedef struct -{ - DWORD dwCuePoints; -#if defined(__GNUC__) && __GNUC__<3 - TAG_CUE_POINT CuePoints[0]; -#elif 1 // change to 0 if compiler fails the following line - TAG_CUE_POINT CuePoints[]; -#else - TAG_CUE_POINT CuePoints[1]; -#endif -} TAG_CUE; - -// RIFF "smpl" tag structures -typedef struct -{ - DWORD dwIdentifier; - DWORD dwType; - DWORD dwStart; - DWORD dwEnd; - DWORD dwFraction; - DWORD dwPlayCount; -} TAG_SMPL_LOOP; - -typedef struct -{ - DWORD dwManufacturer; - DWORD dwProduct; - DWORD dwSamplePeriod; - DWORD dwMIDIUnityNote; - DWORD dwMIDIPitchFraction; - DWORD dwSMPTEFormat; - DWORD dwSMPTEOffset; - DWORD cSampleLoops; - DWORD cbSamplerData; -#if defined(__GNUC__) && __GNUC__<3 - TAG_SMPL_LOOP SampleLoops[0]; -#elif 1 // change to 0 if compiler fails the following line - TAG_SMPL_LOOP SampleLoops[]; -#else - TAG_SMPL_LOOP SampleLoops[1]; -#endif -} TAG_SMPL; -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// CoreAudio codec info structure -typedef struct { - DWORD ftype; // file format - DWORD atype; // audio format - const char *name; // description -} TAG_CA_CODEC; - -#ifndef _WAVEFORMATEX_ -#define _WAVEFORMATEX_ -#pragma pack(push,1) -typedef struct tWAVEFORMATEX -{ - WORD wFormatTag; - WORD nChannels; - DWORD nSamplesPerSec; - DWORD nAvgBytesPerSec; - WORD nBlockAlign; - WORD wBitsPerSample; - WORD cbSize; -} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX; -typedef const WAVEFORMATEX *LPCWAVEFORMATEX; -#pragma pack(pop) -#endif - -// BASS_ChannelGetLength/GetPosition/SetPosition modes -#define BASS_POS_BYTE 0 // byte position -#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row) -#define BASS_POS_OGG 3 // OGG bitstream number -#define BASS_POS_RESET 0x2000000 // flag: reset user file buffers -#define BASS_POS_RELATIVE 0x4000000 // flag: seek relative to the current position -#define BASS_POS_INEXACT 0x8000000 // flag: allow seeking to inexact position -#define BASS_POS_DECODE 0x10000000 // flag: get the decoding (not playing) position -#define BASS_POS_DECODETO 0x20000000 // flag: decode to the position instead of seeking -#define BASS_POS_SCAN 0x40000000 // flag: scan to the position - -// BASS_ChannelSetDevice/GetDevice option -#define BASS_NODEVICE 0x20000 - -// BASS_RecordSetInput flags -#define BASS_INPUT_OFF 0x10000 -#define BASS_INPUT_ON 0x20000 - -#define BASS_INPUT_TYPE_MASK 0xff000000 -#define BASS_INPUT_TYPE_UNDEF 0x00000000 -#define BASS_INPUT_TYPE_DIGITAL 0x01000000 -#define BASS_INPUT_TYPE_LINE 0x02000000 -#define BASS_INPUT_TYPE_MIC 0x03000000 -#define BASS_INPUT_TYPE_SYNTH 0x04000000 -#define BASS_INPUT_TYPE_CD 0x05000000 -#define BASS_INPUT_TYPE_PHONE 0x06000000 -#define BASS_INPUT_TYPE_SPEAKER 0x07000000 -#define BASS_INPUT_TYPE_WAVE 0x08000000 -#define BASS_INPUT_TYPE_AUX 0x09000000 -#define BASS_INPUT_TYPE_ANALOG 0x0a000000 - -// BASS_ChannelSetFX effect types -#define BASS_FX_DX8_CHORUS 0 -#define BASS_FX_DX8_COMPRESSOR 1 -#define BASS_FX_DX8_DISTORTION 2 -#define BASS_FX_DX8_ECHO 3 -#define BASS_FX_DX8_FLANGER 4 -#define BASS_FX_DX8_GARGLE 5 -#define BASS_FX_DX8_I3DL2REVERB 6 -#define BASS_FX_DX8_PARAMEQ 7 -#define BASS_FX_DX8_REVERB 8 -#define BASS_FX_VOLUME 9 - -typedef struct { - float fWetDryMix; - float fDepth; - float fFeedback; - float fFrequency; - DWORD lWaveform; // 0=triangle, 1=sine - float fDelay; - DWORD lPhase; // BASS_DX8_PHASE_xxx -} BASS_DX8_CHORUS; - -typedef struct { - float fGain; - float fAttack; - float fRelease; - float fThreshold; - float fRatio; - float fPredelay; -} BASS_DX8_COMPRESSOR; - -typedef struct { - float fGain; - float fEdge; - float fPostEQCenterFrequency; - float fPostEQBandwidth; - float fPreLowpassCutoff; -} BASS_DX8_DISTORTION; - -typedef struct { - float fWetDryMix; - float fFeedback; - float fLeftDelay; - float fRightDelay; - BOOL lPanDelay; -} BASS_DX8_ECHO; - -typedef struct { - float fWetDryMix; - float fDepth; - float fFeedback; - float fFrequency; - DWORD lWaveform; // 0=triangle, 1=sine - float fDelay; - DWORD lPhase; // BASS_DX8_PHASE_xxx -} BASS_DX8_FLANGER; - -typedef struct { - DWORD dwRateHz; // Rate of modulation in hz - DWORD dwWaveShape; // 0=triangle, 1=square -} BASS_DX8_GARGLE; - -typedef struct { - int lRoom; // [-10000, 0] default: -1000 mB - int lRoomHF; // [-10000, 0] default: 0 mB - float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 - float flDecayTime; // [0.1, 20.0] default: 1.49s - float flDecayHFRatio; // [0.1, 2.0] default: 0.83 - int lReflections; // [-10000, 1000] default: -2602 mB - float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s - int lReverb; // [-10000, 2000] default: 200 mB - float flReverbDelay; // [0.0, 0.1] default: 0.011 s - float flDiffusion; // [0.0, 100.0] default: 100.0 % - float flDensity; // [0.0, 100.0] default: 100.0 % - float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz -} BASS_DX8_I3DL2REVERB; - -typedef struct { - float fCenter; - float fBandwidth; - float fGain; -} BASS_DX8_PARAMEQ; - -typedef struct { - float fInGain; // [-96.0,0.0] default: 0.0 dB - float fReverbMix; // [-96.0,0.0] default: 0.0 db - float fReverbTime; // [0.001,3000.0] default: 1000.0 ms - float fHighFreqRTRatio; // [0.001,0.999] default: 0.001 -} BASS_DX8_REVERB; - -#define BASS_DX8_PHASE_NEG_180 0 -#define BASS_DX8_PHASE_NEG_90 1 -#define BASS_DX8_PHASE_ZERO 2 -#define BASS_DX8_PHASE_90 3 -#define BASS_DX8_PHASE_180 4 - -typedef struct { - float fTarget; - float fCurrent; - float fTime; - DWORD lCurve; -} BASS_FX_VOLUME_PARAM; - -typedef void (CALLBACK IOSNOTIFYPROC)(DWORD status); -/* iOS notification callback function. -status : The notification (BASS_IOSNOTIFY_xxx) */ - -#define BASS_IOSNOTIFY_INTERRUPT 1 // interruption started -#define BASS_IOSNOTIFY_INTERRUPT_END 2 // interruption ended - -BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value); -DWORD BASSDEF(BASS_GetConfig)(DWORD option); -BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value); -void *BASSDEF(BASS_GetConfigPtr)(DWORD option); -DWORD BASSDEF(BASS_GetVersion)(); -int BASSDEF(BASS_ErrorGetCode)(); -BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); -#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) -BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const GUID *dsguid); -#else -BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, void *dsguid); -#endif -BOOL BASSDEF(BASS_SetDevice)(DWORD device); -DWORD BASSDEF(BASS_GetDevice)(); -BOOL BASSDEF(BASS_Free)(); -#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) -void *BASSDEF(BASS_GetDSoundObject)(DWORD object); -#endif -BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info); -BOOL BASSDEF(BASS_Update)(DWORD length); -float BASSDEF(BASS_GetCPU)(); -BOOL BASSDEF(BASS_Start)(); -BOOL BASSDEF(BASS_Stop)(); -BOOL BASSDEF(BASS_Pause)(); -BOOL BASSDEF(BASS_IsStarted)(); -BOOL BASSDEF(BASS_SetVolume)(float volume); -float BASSDEF(BASS_GetVolume)(); - -HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags); -BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle); -const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle); - -BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf); -BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf); -BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top); -BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top); -void BASSDEF(BASS_Apply3D)(); -#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) -BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay, float damp); -BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay, float *damp); -#endif - -HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq); -BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle); - -HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags); -HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags); -BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle); -BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer); -BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer); -BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info); -BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info); -HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew); -DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels); -BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle); - -HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user); -HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); -HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user); -HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user); -BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle); -QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode); -DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length); -DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length); - -BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); -BOOL BASSDEF(BASS_RecordInit)(int device); -BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device); -DWORD BASSDEF(BASS_RecordGetDevice)(); -BOOL BASSDEF(BASS_RecordFree)(); -BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info); -const char *BASSDEF(BASS_RecordGetInputName)(int input); -BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume); -DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume); -HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user); - -double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos); -QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos); -DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle); -BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device); -DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle); -BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info); -const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags); -DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask); -BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length); -BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock); -BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart); -BOOL BASSDEF(BASS_ChannelStop)(DWORD handle); -BOOL BASSDEF(BASS_ChannelPause)(DWORD handle); -BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value); -BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value); -BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time); -BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib); -BOOL BASSDEF(BASS_ChannelSetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size); -DWORD BASSDEF(BASS_ChannelGetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size); -BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol); -BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol); -BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel); -BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel); -QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode); -BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode); -QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode); -DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle); -BOOL BASSDEF(BASS_ChannelGetLevelEx)(DWORD handle, float *levels, float length, DWORD flags); -DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length); -HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user); -BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync); -HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority); -BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp); -BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan); -BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan); -HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority); -BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx); - -BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params); -BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params); -BOOL BASSDEF(BASS_FXReset)(HFX handle); -BOOL BASSDEF(BASS_FXSetPriority)(HFX handle, int priority); - -#ifdef __cplusplus -} - -#if defined(_WIN32) && !defined(NOBASSOVERLOADS) -static inline HPLUGIN BASS_PluginLoad(const WCHAR *file, DWORD flags) -{ - return BASS_PluginLoad((const char*)file, flags|BASS_UNICODE); -} - -static inline HMUSIC BASS_MusicLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD flags, DWORD freq) -{ - return BASS_MusicLoad(mem, (const void*)file, offset, length, flags|BASS_UNICODE, freq); -} - -static inline HSAMPLE BASS_SampleLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD max, DWORD flags) -{ - return BASS_SampleLoad(mem, (const void*)file, offset, length, max, flags|BASS_UNICODE); -} - -static inline HSTREAM BASS_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags) -{ - return BASS_StreamCreateFile(mem, (const void*)file, offset, length, flags|BASS_UNICODE); -} - -static inline HSTREAM BASS_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user) -{ - return BASS_StreamCreateURL((const char*)url, offset, flags|BASS_UNICODE, proc, user); -} - -static inline BOOL BASS_SetConfigPtr(DWORD option, const WCHAR *value) -{ - return BASS_SetConfigPtr(option|BASS_UNICODE, (const void*)value); -} -#endif -#endif - -#endif diff --git a/hsmodem/bass.lib b/hsmodem/bass.lib deleted file mode 100755 index 0f04905..0000000 Binary files a/hsmodem/bass.lib and /dev/null differ diff --git a/hsmodem/bassenc.h b/hsmodem/bassenc.h deleted file mode 100644 index 9e3d55c..0000000 --- a/hsmodem/bassenc.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - BASSenc 2.4 C/C++ header file - Copyright (c) 2003-2018 Un4seen Developments Ltd. - - See the BASSENC.CHM file for more detailed documentation -*/ - -#ifndef BASSENC_H -#define BASSENC_H - -#include "bass.h" - -#if BASSVERSION!=0x204 -#error conflicting BASS and BASSenc versions -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef BASSENCDEF -#define BASSENCDEF(f) WINAPI f -#endif - -typedef DWORD HENCODE; // encoder handle - -// Additional error codes returned by BASS_ErrorGetCode -#define BASS_ERROR_ACM_CANCEL 2000 // ACM codec selection cancelled -#define BASS_ERROR_CAST_DENIED 2100 // access denied (invalid password) - -// Additional BASS_SetConfig options -#define BASS_CONFIG_ENCODE_PRIORITY 0x10300 -#define BASS_CONFIG_ENCODE_QUEUE 0x10301 -#define BASS_CONFIG_ENCODE_CAST_TIMEOUT 0x10310 - -// Additional BASS_SetConfigPtr options -#define BASS_CONFIG_ENCODE_ACM_LOAD 0x10302 -#define BASS_CONFIG_ENCODE_CAST_PROXY 0x10311 - -// BASS_Encode_Start flags -#define BASS_ENCODE_NOHEAD 1 // don't send a WAV header to the encoder -#define BASS_ENCODE_FP_8BIT 2 // convert floating-point sample data to 8-bit integer -#define BASS_ENCODE_FP_16BIT 4 // convert floating-point sample data to 16-bit integer -#define BASS_ENCODE_FP_24BIT 6 // convert floating-point sample data to 24-bit integer -#define BASS_ENCODE_FP_32BIT 8 // convert floating-point sample data to 32-bit integer -#define BASS_ENCODE_FP_AUTO 14 // convert floating-point sample data back to channel's format -#define BASS_ENCODE_BIGEND 16 // big-endian sample data -#define BASS_ENCODE_PAUSE 32 // start encording paused -#define BASS_ENCODE_PCM 64 // write PCM sample data (no encoder) -#define BASS_ENCODE_RF64 128 // send an RF64 header -#define BASS_ENCODE_MONO 0x100 // convert to mono (if not already) -#define BASS_ENCODE_QUEUE 0x200 // queue data to feed encoder asynchronously -#define BASS_ENCODE_WFEXT 0x400 // WAVEFORMATEXTENSIBLE "fmt" chunk -#define BASS_ENCODE_CAST_NOLIMIT 0x1000 // don't limit casting data rate -#define BASS_ENCODE_LIMIT 0x2000 // limit data rate to real-time -#define BASS_ENCODE_AIFF 0x4000 // send an AIFF header rather than WAV -#define BASS_ENCODE_DITHER 0x8000 // apply dither when converting floating-point sample data to integer -#define BASS_ENCODE_AUTOFREE 0x40000 // free the encoder when the channel is freed - -// BASS_Encode_GetACMFormat flags -#define BASS_ACM_DEFAULT 1 // use the format as default selection -#define BASS_ACM_RATE 2 // only list formats with same sample rate as the source channel -#define BASS_ACM_CHANS 4 // only list formats with same number of channels (eg. mono/stereo) -#define BASS_ACM_SUGGEST 8 // suggest a format (HIWORD=format tag) - -// BASS_Encode_GetCount counts -#define BASS_ENCODE_COUNT_IN 0 // sent to encoder -#define BASS_ENCODE_COUNT_OUT 1 // received from encoder -#define BASS_ENCODE_COUNT_CAST 2 // sent to cast server -#define BASS_ENCODE_COUNT_QUEUE 3 // queued -#define BASS_ENCODE_COUNT_QUEUE_LIMIT 4 // queue limit -#define BASS_ENCODE_COUNT_QUEUE_FAIL 5 // failed to queue - -// BASS_Encode_CastInit content MIME types -#define BASS_ENCODE_TYPE_MP3 "audio/mpeg" -#define BASS_ENCODE_TYPE_OGG "audio/ogg" -#define BASS_ENCODE_TYPE_AAC "audio/aacp" - -// BASS_Encode_CastGetStats types -#define BASS_ENCODE_STATS_SHOUT 0 // Shoutcast stats -#define BASS_ENCODE_STATS_ICE 1 // Icecast mount-point stats -#define BASS_ENCODE_STATS_ICESERV 2 // Icecast server stats - -typedef void (CALLBACK ENCODEPROC)(HENCODE handle, DWORD channel, const void *buffer, DWORD length, void *user); -/* Encoding callback function. -handle : The encoder -channel: The channel handle -buffer : Buffer containing the encoded data -length : Number of bytes -user : The 'user' parameter value given when starting the encoder */ - -typedef void (CALLBACK ENCODEPROCEX)(HENCODE handle, DWORD channel, const void *buffer, DWORD length, QWORD offset, void *user); -/* Encoding callback function with offset info. -handle : The encoder -channel: The channel handle -buffer : Buffer containing the encoded data -length : Number of bytes -offset : File offset of the data -user : The 'user' parameter value given when starting the encoder */ - -typedef DWORD (CALLBACK ENCODERPROC)(HENCODE handle, DWORD channel, void *buffer, DWORD length, DWORD maxout, void *user); -/* Encoder callback function. -handle : The encoder -channel: The channel handle -buffer : Buffer containing the PCM data (input) and receiving the encoded data (output) -length : Number of bytes in (-1=closing) -maxout : Maximum number of bytes out -user : The 'user' parameter value given when calling BASS_Encode_StartUser -RETURN : The amount of encoded data (-1=stop) */ - -typedef BOOL (CALLBACK ENCODECLIENTPROC)(HENCODE handle, BOOL connect, const char *client, char *headers, void *user); -/* Client connection notification callback function. -handle : The encoder -connect: TRUE/FALSE=client is connecting/disconnecting -client : The client's address (xxx.xxx.xxx.xxx:port) -headers: Request headers (optionally response headers on return) -user : The 'user' parameter value given when calling BASS_Encode_ServerInit -RETURN : TRUE/FALSE=accept/reject connection (ignored if connect=FALSE) */ - -typedef void (CALLBACK ENCODENOTIFYPROC)(HENCODE handle, DWORD status, void *user); -/* Encoder death notification callback function. -handle : The encoder -status : Notification (BASS_ENCODE_NOTIFY_xxx) -user : The 'user' parameter value given when calling BASS_Encode_SetNotify */ - -// Encoder notifications -#define BASS_ENCODE_NOTIFY_ENCODER 1 // encoder died -#define BASS_ENCODE_NOTIFY_CAST 2 // cast server connection died -#define BASS_ENCODE_NOTIFY_CAST_TIMEOUT 0x10000 // cast timeout -#define BASS_ENCODE_NOTIFY_QUEUE_FULL 0x10001 // queue is out of space -#define BASS_ENCODE_NOTIFY_FREE 0x10002 // encoder has been freed - -// BASS_Encode_ServerInit flags -#define BASS_ENCODE_SERVER_NOHTTP 1 // no HTTP headers -#define BASS_ENCODE_SERVER_META 2 // Shoutcast metadata - -DWORD BASSENCDEF(BASS_Encode_GetVersion)(); - -HENCODE BASSENCDEF(BASS_Encode_Start)(DWORD handle, const char *cmdline, DWORD flags, ENCODEPROC *proc, void *user); -HENCODE BASSENCDEF(BASS_Encode_StartLimit)(DWORD handle, const char *cmdline, DWORD flags, ENCODEPROC *proc, void *user, DWORD limit); -HENCODE BASSENCDEF(BASS_Encode_StartUser)(DWORD handle, const char *filename, DWORD flags, ENCODERPROC *proc, void *user); -BOOL BASSENCDEF(BASS_Encode_AddChunk)(HENCODE handle, const char *id, const void *buffer, DWORD length); -DWORD BASSENCDEF(BASS_Encode_IsActive)(DWORD handle); -BOOL BASSENCDEF(BASS_Encode_Stop)(DWORD handle); -BOOL BASSENCDEF(BASS_Encode_StopEx)(DWORD handle, BOOL queue); -BOOL BASSENCDEF(BASS_Encode_SetPaused)(DWORD handle, BOOL paused); -BOOL BASSENCDEF(BASS_Encode_Write)(DWORD handle, const void *buffer, DWORD length); -BOOL BASSENCDEF(BASS_Encode_SetNotify)(DWORD handle, ENCODENOTIFYPROC *proc, void *user); -QWORD BASSENCDEF(BASS_Encode_GetCount)(DWORD handle, DWORD count); -BOOL BASSENCDEF(BASS_Encode_SetChannel)(DWORD handle, DWORD channel); -DWORD BASSENCDEF(BASS_Encode_GetChannel)(HENCODE handle); -BOOL BASSENCDEF(BASS_Encode_UserOutput)(DWORD handle, QWORD offset, const void *buffer, DWORD length); - -#ifdef _WIN32 -DWORD BASSENCDEF(BASS_Encode_GetACMFormat)(DWORD handle, void *form, DWORD formlen, const char *title, DWORD flags); -HENCODE BASSENCDEF(BASS_Encode_StartACM)(DWORD handle, const void *form, DWORD flags, ENCODEPROC *proc, void *user); -HENCODE BASSENCDEF(BASS_Encode_StartACMFile)(DWORD handle, const void *form, DWORD flags, const char *filename); -#endif - -#ifdef __APPLE__ -HENCODE BASSENCDEF(BASS_Encode_StartCA)(DWORD handle, DWORD ftype, DWORD atype, DWORD flags, DWORD bitrate, ENCODEPROCEX *proc, void *user); -HENCODE BASSENCDEF(BASS_Encode_StartCAFile)(DWORD handle, DWORD ftype, DWORD atype, DWORD flags, DWORD bitrate, const char *filename); -void *BASSENCDEF(BASS_Encode_GetCARef)(DWORD handle); -#endif - -#ifndef _WIN32_WCE -BOOL BASSENCDEF(BASS_Encode_CastInit)(HENCODE handle, const char *server, const char *pass, const char *content, const char *name, const char *url, const char *genre, const char *desc, const char *headers, DWORD bitrate, BOOL pub); -BOOL BASSENCDEF(BASS_Encode_CastSetTitle)(HENCODE handle, const char *title, const char *url); -BOOL BASSENCDEF(BASS_Encode_CastSendMeta)(HENCODE handle, DWORD type, const void *data, DWORD length); -const char *BASSENCDEF(BASS_Encode_CastGetStats)(HENCODE handle, DWORD type, const char *pass); - -DWORD BASSENCDEF(BASS_Encode_ServerInit)(HENCODE handle, const char *port, DWORD buffer, DWORD burst, DWORD flags, ENCODECLIENTPROC *proc, void *user); -BOOL BASSENCDEF(BASS_Encode_ServerKick)(HENCODE handle, const char *client); -#endif - -#ifdef __cplusplus -} - -#ifdef _WIN32 -static inline HENCODE BASS_Encode_Start(DWORD handle, const WCHAR *cmdline, DWORD flags, ENCODEPROC *proc, void *user) -{ - return BASS_Encode_Start(handle, (const char*)cmdline, flags|BASS_UNICODE, proc, user); -} - -static inline HENCODE BASS_Encode_StartLimit(DWORD handle, const WCHAR *cmdline, DWORD flags, ENCODEPROC *proc, void *user, DWORD limit) -{ - return BASS_Encode_StartLimit(handle, (const char *)cmdline, flags|BASS_UNICODE, proc, user, limit); -} - -static inline HENCODE BASS_Encode_StartUser(DWORD handle, const WCHAR *filename, DWORD flags, ENCODERPROC *proc, void *user) -{ - return BASS_Encode_StartUser(handle, (const char *)filename, flags|BASS_UNICODE, proc, user); -} - -static inline DWORD BASS_Encode_GetACMFormat(DWORD handle, void *form, DWORD formlen, const WCHAR *title, DWORD flags) -{ - return BASS_Encode_GetACMFormat(handle, form, formlen, (const char *)title, flags|BASS_UNICODE); -} - -static inline HENCODE BASS_Encode_StartACMFile(DWORD handle, const void *form, DWORD flags, const WCHAR *filename) -{ - return BASS_Encode_StartACMFile(handle, form, flags|BASS_UNICODE, (const char *)filename); -} -#endif -#endif - -#endif diff --git a/hsmodem/bassenc_opus.h b/hsmodem/bassenc_opus.h deleted file mode 100644 index 94ce78c..0000000 --- a/hsmodem/bassenc_opus.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - BASSenc_OPUS 2.4 C/C++ header file - Copyright (c) 2016 Un4seen Developments Ltd. - - See the BASSENC_OPUS.CHM file for more detailed documentation -*/ - -#ifndef BASSENC_OPUS_H -#define BASSENC_OPUS_H - -#include "bassenc.h" - -#if BASSVERSION!=0x204 -#error conflicting BASS and BASSenc_OPUS versions -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef BASSENCOPUSDEF -#define BASSENCOPUSDEF(f) WINAPI f -#endif - -DWORD BASSENCOPUSDEF(BASS_Encode_OPUS_GetVersion)(); - -HENCODE BASSENCOPUSDEF(BASS_Encode_OPUS_Start)(DWORD handle, const char *options, DWORD flags, ENCODEPROC *proc, void *user); -HENCODE BASSENCOPUSDEF(BASS_Encode_OPUS_StartFile)(DWORD handle, const char *options, DWORD flags, const char *filename); - -#ifdef __cplusplus -} - -#ifdef _WIN32 -static inline HENCODE BASS_Encode_OPUS_Start(DWORD handle, const WCHAR *options, DWORD flags, ENCODEPROC *proc, void *user) -{ - return BASS_Encode_OPUS_Start(handle, (const char*)options, flags|BASS_UNICODE, proc, user); -} - -static inline HENCODE BASS_Encode_OPUS_StartFile(DWORD handle, const WCHAR *options, DWORD flags, const WCHAR *filename) -{ - return BASS_Encode_OPUS_StartFile(handle, (const char*)options, flags|BASS_UNICODE, (const char*)filename); -} -#endif -#endif - -#endif diff --git a/hsmodem/bassflac.h b/hsmodem/bassflac.h deleted file mode 100644 index c9daa20..0000000 --- a/hsmodem/bassflac.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - BASSFLAC 2.4 C/C++ header file - Copyright (c) 2004-2017 Un4seen Developments Ltd. - - See the BASSFLAC.CHM file for more detailed documentation -*/ - -#ifndef BASSFLAC_H -#define BASSFLAC_H - -#include "bass.h" - -#if BASSVERSION!=0x204 -#error conflicting BASS and BASSFLAC versions -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef BASSFLACDEF -#define BASSFLACDEF(f) WINAPI f -#endif - -// BASS_CHANNELINFO type -#define BASS_CTYPE_STREAM_FLAC 0x10900 -#define BASS_CTYPE_STREAM_FLAC_OGG 0x10901 - -// Additional tag types -#define BASS_TAG_FLAC_CUE 12 // cuesheet : TAG_FLAC_CUE structure -#define BASS_TAG_FLAC_PICTURE 0x12000 // + index #, picture : TAG_FLAC_PICTURE structure -#define BASS_TAG_FLAC_METADATA 0x12400 // + index #, application metadata : TAG_FLAC_METADATA structure - -typedef struct { - DWORD apic; // ID3v2 "APIC" picture type - const char *mime; // mime type - const char *desc; // description - DWORD width; - DWORD height; - DWORD depth; - DWORD colors; - DWORD length; // data length - const void *data; -} TAG_FLAC_PICTURE; - -typedef struct { - QWORD offset; // index offset relative to track offset (samples) - DWORD number; // index number -} TAG_FLAC_CUE_TRACK_INDEX; - -typedef struct { - QWORD offset; // track offset (samples) - DWORD number; // track number - const char *isrc; // ISRC - DWORD flags; - DWORD nindexes; // number of indexes - const TAG_FLAC_CUE_TRACK_INDEX *indexes; // the indexes -} TAG_FLAC_CUE_TRACK; - -typedef struct { - const char *catalog; // media catalog number - DWORD leadin; // lead-in (samples) - BOOL iscd; // a CD? - DWORD ntracks; // number of tracks - const TAG_FLAC_CUE_TRACK *tracks; // the tracks -} TAG_FLAC_CUE; - -// TAG_FLAC_CUE_TRACK flags -#define TAG_FLAC_CUE_TRACK_DATA 1 // data track -#define TAG_FLAC_CUE_TRACK_PRE 2 // pre-emphasis - -typedef struct { - char id[4]; - DWORD length; // data length - const void *data; -} TAG_FLAC_METADATA; - -HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); -HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user); -HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user); - -#ifdef __cplusplus -} - -#ifdef _WIN32 -static inline HSTREAM BASS_FLAC_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags) -{ - return BASS_FLAC_StreamCreateFile(mem, (const void*)file, offset, length, flags|BASS_UNICODE); -} - -static inline HSTREAM BASS_FLAC_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user) -{ - return BASS_FLAC_StreamCreateURL((const char*)url, offset, flags|BASS_UNICODE, proc, user); -} -#endif -#endif - -#endif diff --git a/hsmodem/basswasapi.h b/hsmodem/basswasapi.h deleted file mode 100755 index 6497793..0000000 --- a/hsmodem/basswasapi.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - BASSWASAPI 2.4 C/C++ header file - Copyright (c) 2009-2020 Un4seen Developments Ltd. - - See the BASSWASAPI.CHM file for more detailed documentation -*/ - -#ifndef BASSWASAPI_H -#define BASSWASAPI_H - -#include "bass.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef BASSWASAPIDEF -#define BASSWASAPIDEF(f) WINAPI f -#endif - -// Additional error codes returned by BASS_ErrorGetCode -#define BASS_ERROR_WASAPI 5000 // no WASAPI -#define BASS_ERROR_WASAPI_BUFFER 5001 // buffer size is invalid -#define BASS_ERROR_WASAPI_CATEGORY 5002 // can't set category -#define BASS_ERROR_WASAPI_DENIED 5003 // access denied - -// Device info structure -typedef struct { - const char *name; - const char *id; - DWORD type; - DWORD flags; - float minperiod; - float defperiod; - DWORD mixfreq; - DWORD mixchans; -} BASS_WASAPI_DEVICEINFO; - -typedef struct { - DWORD initflags; - DWORD freq; - DWORD chans; - DWORD format; - DWORD buflen; - float volmax; - float volmin; - float volstep; -} BASS_WASAPI_INFO; - -// BASS_WASAPI_DEVICEINFO "type" -#define BASS_WASAPI_TYPE_NETWORKDEVICE 0 -#define BASS_WASAPI_TYPE_SPEAKERS 1 -#define BASS_WASAPI_TYPE_LINELEVEL 2 -#define BASS_WASAPI_TYPE_HEADPHONES 3 -#define BASS_WASAPI_TYPE_MICROPHONE 4 -#define BASS_WASAPI_TYPE_HEADSET 5 -#define BASS_WASAPI_TYPE_HANDSET 6 -#define BASS_WASAPI_TYPE_DIGITAL 7 -#define BASS_WASAPI_TYPE_SPDIF 8 -#define BASS_WASAPI_TYPE_HDMI 9 -#define BASS_WASAPI_TYPE_UNKNOWN 10 - -// BASS_WASAPI_DEVICEINFO flags -#define BASS_DEVICE_ENABLED 1 -#define BASS_DEVICE_DEFAULT 2 -#define BASS_DEVICE_INIT 4 -#define BASS_DEVICE_LOOPBACK 8 -#define BASS_DEVICE_INPUT 16 -#define BASS_DEVICE_UNPLUGGED 32 -#define BASS_DEVICE_DISABLED 64 - -// BASS_WASAPI_Init flags -#define BASS_WASAPI_EXCLUSIVE 1 -#define BASS_WASAPI_AUTOFORMAT 2 -#define BASS_WASAPI_BUFFER 4 -#define BASS_WASAPI_EVENT 16 -#define BASS_WASAPI_SAMPLES 32 -#define BASS_WASAPI_DITHER 64 -#define BASS_WASAPI_RAW 128 -#define BASS_WASAPI_ASYNC 0x100 - -#define BASS_WASAPI_CATEGORY_MASK 0xf000 -#define BASS_WASAPI_CATEGORY_OTHER 0x0000 -#define BASS_WASAPI_CATEGORY_FOREGROUNDONLYMEDIA 0x1000 -#define BASS_WASAPI_CATEGORY_BACKGROUNDCAPABLEMEDIA 0x2000 -#define BASS_WASAPI_CATEGORY_COMMUNICATIONS 0x3000 -#define BASS_WASAPI_CATEGORY_ALERTS 0x4000 -#define BASS_WASAPI_CATEGORY_SOUNDEFFECTS 0x5000 -#define BASS_WASAPI_CATEGORY_GAMEEFFECTS 0x6000 -#define BASS_WASAPI_CATEGORY_GAMEMEDIA 0x7000 -#define BASS_WASAPI_CATEGORY_GAMECHAT 0x8000 -#define BASS_WASAPI_CATEGORY_SPEECH 0x9000 -#define BASS_WASAPI_CATEGORY_MOVIE 0xa000 -#define BASS_WASAPI_CATEGORY_MEDIA 0xb000 - -// BASS_WASAPI_INFO "format" -#define BASS_WASAPI_FORMAT_FLOAT 0 -#define BASS_WASAPI_FORMAT_8BIT 1 -#define BASS_WASAPI_FORMAT_16BIT 2 -#define BASS_WASAPI_FORMAT_24BIT 3 -#define BASS_WASAPI_FORMAT_32BIT 4 - -// BASS_WASAPI_Set/GetVolume modes -#define BASS_WASAPI_CURVE_DB 0 -#define BASS_WASAPI_CURVE_LINEAR 1 -#define BASS_WASAPI_CURVE_WINDOWS 2 -#define BASS_WASAPI_VOL_SESSION 8 - -typedef DWORD (CALLBACK WASAPIPROC)(void *buffer, DWORD length, void *user); -/* WASAPI callback function. -buffer : Buffer containing the sample data -length : Number of bytes -user : The 'user' parameter given when calling BASS_WASAPI_Init -RETURN : The number of bytes written (output devices), 0/1 = stop/continue (input devices) */ - -// Special WASAPIPROCs -#define WASAPIPROC_PUSH (WASAPIPROC*)0 // push output -#define WASAPIPROC_BASS (WASAPIPROC*)-1 // BASS channel - -typedef void (CALLBACK WASAPINOTIFYPROC)(DWORD notify, DWORD device, void *user); -/* WASAPI device notification callback function. -notify : The notification (BASS_WASAPI_NOTIFY_xxx) -device : Device that the notification applies to -user : The 'user' parameter given when calling BASS_WASAPI_SetNotify */ - -// Device notifications -#define BASS_WASAPI_NOTIFY_ENABLED 0 -#define BASS_WASAPI_NOTIFY_DISABLED 1 -#define BASS_WASAPI_NOTIFY_DEFOUTPUT 2 -#define BASS_WASAPI_NOTIFY_DEFINPUT 3 -#define BASS_WASAPI_NOTIFY_FAIL 0x100 - -DWORD BASSWASAPIDEF(BASS_WASAPI_GetVersion)(); -BOOL BASSWASAPIDEF(BASS_WASAPI_SetNotify)(WASAPINOTIFYPROC *proc, void *user); -BOOL BASSWASAPIDEF(BASS_WASAPI_GetDeviceInfo)(DWORD device, BASS_WASAPI_DEVICEINFO *info); -float BASSWASAPIDEF(BASS_WASAPI_GetDeviceLevel)(DWORD device, int chan); -BOOL BASSWASAPIDEF(BASS_WASAPI_SetDevice)(DWORD device); -DWORD BASSWASAPIDEF(BASS_WASAPI_GetDevice)(); -DWORD BASSWASAPIDEF(BASS_WASAPI_CheckFormat)(DWORD device, DWORD freq, DWORD chans, DWORD flags); -BOOL BASSWASAPIDEF(BASS_WASAPI_Init)(int device, DWORD freq, DWORD chans, DWORD flags, float buffer, float period, WASAPIPROC *proc, void *user); -BOOL BASSWASAPIDEF(BASS_WASAPI_Free)(); -BOOL BASSWASAPIDEF(BASS_WASAPI_GetInfo)(BASS_WASAPI_INFO *info); -float BASSWASAPIDEF(BASS_WASAPI_GetCPU)(); -BOOL BASSWASAPIDEF(BASS_WASAPI_Lock)(BOOL lock); -BOOL BASSWASAPIDEF(BASS_WASAPI_Start)(); -BOOL BASSWASAPIDEF(BASS_WASAPI_Stop)(BOOL reset); -BOOL BASSWASAPIDEF(BASS_WASAPI_IsStarted)(); -BOOL BASSWASAPIDEF(BASS_WASAPI_SetVolume)(DWORD mode, float volume); -float BASSWASAPIDEF(BASS_WASAPI_GetVolume)(DWORD mode); -BOOL BASSWASAPIDEF(BASS_WASAPI_SetMute)(DWORD mode, BOOL mute); -BOOL BASSWASAPIDEF(BASS_WASAPI_GetMute)(DWORD mode); -DWORD BASSWASAPIDEF(BASS_WASAPI_PutData)(void *buffer, DWORD length); -DWORD BASSWASAPIDEF(BASS_WASAPI_GetData)(void *buffer, DWORD length); -DWORD BASSWASAPIDEF(BASS_WASAPI_GetLevel)(); -BOOL BASSWASAPIDEF(BASS_WASAPI_GetLevelEx)(float *levels, float length, DWORD flags); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/hsmodem/basswasapi.lib b/hsmodem/basswasapi.lib deleted file mode 100644 index c7155e3..0000000 Binary files a/hsmodem/basswasapi.lib and /dev/null differ diff --git a/hsmodem/codec2.cpp b/hsmodem/codec2.cpp index 7db49b0..c6d9f89 100755 --- a/hsmodem/codec2.cpp +++ b/hsmodem/codec2.cpp @@ -110,7 +110,7 @@ void encode_codec2(float f) f /= 32768; // here we have 8kS/s, need to interpolate to 48 kS/s for(int x=0; x<6; x++) - pb_write_fifo_voice(f); + io_ls_write_fifo(f); } } } @@ -159,7 +159,7 @@ void toCodecDecoder_codec2(uint8_t* pdata, int len) f /= 32768; // here we have 8kS/s, need to interpolate to 48 kS/s for (int x = 0; x < 6; x++) - pb_write_fifo_voice(f); + io_ls_write_fifo(f); } } } diff --git a/hsmodem/endian.h b/hsmodem/endian.h new file mode 100644 index 0000000..f69072f --- /dev/null +++ b/hsmodem/endian.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015 Andrew Kelley + * + * This file is part of libsoundio, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef SOUNDIO_ENDIAN_H +#define SOUNDIO_ENDIAN_H + +#if defined(__BIG_ENDIAN__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__ARMEB__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__THUMBEB__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__AARCH64EB__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(_MIPSEB) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__MIPSEB) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__MIPSEB__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(_BIG_ENDIAN) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__sparc) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__sparc__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(_POWER) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__powerpc__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__ppc__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__hpux) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__hppa) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(_POWER) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__s390__) +#define SOUNDIO_OS_BIG_ENDIAN +#elif defined(__LITTLE_ENDIAN__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__ARMEL__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__THUMBEL__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__AARCH64EL__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(_MIPSEL) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__MIPSEL) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__MIPSEL__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(_LITTLE_ENDIAN) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__i386__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__alpha__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__ia64) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__ia64__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(_M_IX86) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(_M_IA64) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(_M_ALPHA) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__amd64) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__amd64__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(_M_AMD64) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__x86_64) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__x86_64__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(_M_X64) +#define SOUNDIO_OS_LITTLE_ENDIAN +#elif defined(__bfin__) +#define SOUNDIO_OS_LITTLE_ENDIAN +#else +#error unable to detect endianness +#endif + +#endif diff --git a/hsmodem/fifo.cpp b/hsmodem/fifo.cpp new file mode 100755 index 0000000..954f23c --- /dev/null +++ b/hsmodem/fifo.cpp @@ -0,0 +1,230 @@ +/* +* High Speed modem to transfer data in a 2,7kHz SSB channel +* ========================================================= +* Author: DJ0ABR +* +* (c) DJ0ABR +* www.dj0abr.de +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* fifo.c ... thread safe buffer for audio I/O +* +* +*/ + +#include "hsmodem.h" + +#ifdef _WIN32_ +CRITICAL_SECTION io_cap_crit_sec; +CRITICAL_SECTION io_pb_crit_sec; +#define IO_CAP_LOCK EnterCriticalSection(&io_cap_crit_sec) +#define IO_PB_LOCK EnterCriticalSection(&io_pb_crit_sec) +void IO_CAP_UNLOCK() +{ + if (&io_cap_crit_sec != NULL) + LeaveCriticalSection(&io_cap_crit_sec); +} +void IO_PB_UNLOCK() +{ + if (&io_pb_crit_sec != NULL) + LeaveCriticalSection(&io_pb_crit_sec); +} +#endif + +#ifdef _LINUX_ +pthread_mutex_t io_cap_crit_sec; +pthread_mutex_t io_pb_crit_sec; +#define IO_CAP_LOCK pthread_mutex_lock(&io_cap_crit_sec) +void IO_CAP_UNLOCK() { pthread_mutex_unlock(&io_cap_crit_sec); } +#define IO_PB_LOCK pthread_mutex_lock(&io_pb_crit_sec) +void IO_PB_UNLOCK() { pthread_mutex_unlock(&io_pb_crit_sec); } +#endif + +#define AUDIO_PLAYBACK_BUFLEN (48000 * 15) // space for 10 seconds of samples +#define AUDIO_CAPTURE_BUFLEN (10000) //48000)// * 10) // space for 10 seconds of samples + +int io_cap_wridx = 0; +int io_cap_rdidx = 0; +float io_cap_buffer[AUDIO_CAPTURE_BUFLEN]; + +int io_pb_wridx = 0; +int io_pb_rdidx = 0; +float io_pb_buffer[AUDIO_PLAYBACK_BUFLEN]; + +void io_init_pipes() +{ +#ifdef _WIN32_ + if (&io_cap_crit_sec != NULL) DeleteCriticalSection(&io_cap_crit_sec); + InitializeCriticalSection(&io_cap_crit_sec); + + if (&io_pb_crit_sec != NULL) DeleteCriticalSection(&io_pb_crit_sec); + InitializeCriticalSection(&io_pb_crit_sec); + + io_clear_audio_fifos(); +#endif + + io_voice_init_pipes(); +} + +// write one sample into the fifo +// overwrite old data if the fifo is full +void io_cap_write_fifo(float sample) +{ + if (((io_cap_wridx + 1) % AUDIO_CAPTURE_BUFLEN) == io_cap_rdidx) + { + printf("cap fifo full\n"); + } + + IO_CAP_LOCK; + io_cap_buffer[io_cap_wridx] = sample; + if (++io_cap_wridx >= AUDIO_CAPTURE_BUFLEN) io_cap_wridx = 0; + IO_CAP_UNLOCK(); + + // if monitoring is activated then write it also to the voice fifo + /*if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN) + toVoice(sample);*/ +} + +int io_cap_read_fifo(float* data) +{ + IO_CAP_LOCK; + + if (io_cap_rdidx == io_cap_wridx) + { + // Fifo empty, no data available + IO_CAP_UNLOCK(); + return 0; + } + + *data = io_cap_buffer[io_cap_rdidx]; + if (++io_cap_rdidx >= AUDIO_CAPTURE_BUFLEN) io_cap_rdidx = 0; + IO_CAP_UNLOCK(); + + return 1; +} + + +void io_cap_write_fifo_clear() +{ + io_cap_wridx = io_cap_rdidx = 0; +} + +int io_cap_fifo_freespace() +{ + int freebuf = 0; + + IO_CAP_LOCK; + + int elemInFifo = (io_cap_wridx + AUDIO_CAPTURE_BUFLEN - io_cap_rdidx) % AUDIO_CAPTURE_BUFLEN; + freebuf = AUDIO_CAPTURE_BUFLEN - elemInFifo; + + IO_CAP_UNLOCK(); + + return freebuf; +} + +int io_cap_fifo_usedPercent() +{ + int fs = io_cap_fifo_freespace(); + int used = AUDIO_CAPTURE_BUFLEN - fs; + used = (used * 100) / AUDIO_CAPTURE_BUFLEN; + return used; +} + +void io_pb_write_fifo(float sample) +{ + IO_PB_LOCK; + + // check if there is free space in fifo + if (io_pb_fifo_freespace(1) == 0) + { + IO_PB_UNLOCK(); + printf("************* pb fifo full\n"); + return; + } + + io_pb_buffer[io_pb_wridx] = sample; + if (++io_pb_wridx >= AUDIO_PLAYBACK_BUFLEN) io_pb_wridx = 0; + IO_PB_UNLOCK(); + //printf("write: pbw:%d pbr:%d\n",io_pb_wridx,io_pb_rdidx); +} + +void io_pb_write_fifo_clear() +{ + io_pb_wridx = io_pb_rdidx = 0; +} + +int io_pb_fifo_usedBlocks() +{ + int fs = io_pb_fifo_freespace(0); + int used = AUDIO_PLAYBACK_BUFLEN - fs; + used /= (txinterpolfactor * UDPBLOCKLEN * 8 / bitsPerSymbol); + return used; +} + +int io_pb_fifo_freespace(int nolock) +{ + int freebuf = 0; + + if (nolock == 0) IO_PB_LOCK; + + int elemInFifo = (io_pb_wridx + AUDIO_PLAYBACK_BUFLEN - io_pb_rdidx) % AUDIO_PLAYBACK_BUFLEN; + freebuf = AUDIO_PLAYBACK_BUFLEN - elemInFifo; + + if (nolock == 0) IO_PB_UNLOCK(); + + //printf("fifolen:%d check: pbw:%d pbr:%d freebuf:%d\n",AUDIO_PLAYBACK_BUFLEN,io_pb_wridx,io_pb_rdidx,freebuf); + + return freebuf; +} + +int io_pb_fifo_usedspace() +{ + int anz = io_pb_fifo_freespace(0); + return AUDIO_PLAYBACK_BUFLEN - anz; +} + +// read num elements +// if num elems not avail, return 0 +int io_pb_read_fifo_num(float* data, int num) +{ + IO_PB_LOCK; + + int elemInFifo = (io_pb_wridx + AUDIO_PLAYBACK_BUFLEN - io_pb_rdidx) % AUDIO_PLAYBACK_BUFLEN; + + if (elemInFifo < num) + { + // Fifo empty, no data available + //printf("only %d elements available\n", elemInFifo); + IO_PB_UNLOCK(); + return 0; + } + + for (int i = 0; i < num; i++) + { + *data++ = io_pb_buffer[io_pb_rdidx]; + if (++io_pb_rdidx >= AUDIO_PLAYBACK_BUFLEN) io_pb_rdidx = 0; + } + IO_PB_UNLOCK(); + + return 1; +} + +void io_clear_audio_fifos() +{ + io_pb_write_fifo_clear(); + io_cap_write_fifo_clear(); +} diff --git a/hsmodem/fifo_voice.cpp b/hsmodem/fifo_voice.cpp new file mode 100755 index 0000000..98fd3bf --- /dev/null +++ b/hsmodem/fifo_voice.cpp @@ -0,0 +1,218 @@ +/* +* High Speed modem to transfer data in a 2,7kHz SSB channel +* ========================================================= +* Author: DJ0ABR +* +* (c) DJ0ABR +* www.dj0abr.de +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* fifo_voice.c ... thread safe buffer for DV audio +* +* +*/ + +#include "hsmodem.h" + +#ifdef _WIN32_ +CRITICAL_SECTION io_mic_crit_sec; +CRITICAL_SECTION io_ls_crit_sec; +#define IO_MIC_LOCK EnterCriticalSection(&io_mic_crit_sec) +#define IO_LS_LOCK EnterCriticalSection(&io_ls_crit_sec) +void IO_MIC_UNLOCK() +{ + if (&io_mic_crit_sec != NULL) + LeaveCriticalSection(&io_mic_crit_sec); +} +void IO_LS_UNLOCK() +{ + if (&io_ls_crit_sec != NULL) + LeaveCriticalSection(&io_ls_crit_sec); +} +#endif + +#ifdef _LINUX_ +pthread_mutex_t io_mic_crit_sec; +pthread_mutex_t io_ls_crit_sec; +#define IO_MIC_LOCK pthread_mutex_lock(&io_mic_crit_sec) +void IO_MIC_UNLOCK() { pthread_mutex_unlock(&io_mic_crit_sec); } +#define IO_LS_LOCK pthread_mutex_lock(&io_ls_crit_sec) +void IO_LS_UNLOCK() { pthread_mutex_unlock(&io_ls_crit_sec); } +#endif + +#define VOICE_PLAYBACK_BUFLEN (48000 * 15) // space for 10 seconds of samples +#define VOICE_CAPTURE_BUFLEN (10000) //48000)// * 10) // space for 10 seconds of samples + +int io_mic_wridx = 0; +int io_mic_rdidx = 0; +float io_mic_buffer[VOICE_CAPTURE_BUFLEN]; + +int io_ls_wridx = 0; +int io_ls_rdidx = 0; +float io_ls_buffer[VOICE_PLAYBACK_BUFLEN]; + +void io_voice_init_pipes() +{ +#ifdef _WIN32_ + if (&io_mic_crit_sec != NULL) DeleteCriticalSection(&io_mic_crit_sec); + InitializeCriticalSection(&io_mic_crit_sec); + + if (&io_ls_crit_sec != NULL) DeleteCriticalSection(&io_ls_crit_sec); + InitializeCriticalSection(&io_ls_crit_sec); + + io_clear_audio_fifos(); +#endif +} + +// write one sample into the fifo +// overwrite old data if the fifo is full +void io_mic_write_fifo(float sample) +{ + IO_MIC_LOCK; + + if (((io_mic_wridx + 1) % VOICE_CAPTURE_BUFLEN) == io_mic_rdidx) + { + //printf("mic fifo full\n"); + IO_MIC_UNLOCK(); + return; + } + + io_mic_buffer[io_mic_wridx] = sample; + if (++io_mic_wridx >= VOICE_CAPTURE_BUFLEN) io_mic_wridx = 0; + IO_MIC_UNLOCK(); +} + +int io_mic_read_fifo(float* data) +{ + IO_MIC_LOCK; + + if (io_mic_rdidx == io_mic_wridx) + { + // Fifo empty, no data available + IO_MIC_UNLOCK(); + return 0; + } + + *data = io_mic_buffer[io_mic_rdidx]; + if (++io_mic_rdidx >= VOICE_CAPTURE_BUFLEN) io_mic_rdidx = 0; + IO_MIC_UNLOCK(); + + return 1; +} + + +void io_mic_write_fifo_clear() +{ + io_mic_wridx = io_mic_rdidx = 0; +} + +int io_mic_fifo_freespace() +{ + int freebuf = 0; + + IO_MIC_LOCK; + + int elemInFifo = (io_mic_wridx + VOICE_CAPTURE_BUFLEN - io_mic_rdidx) % VOICE_CAPTURE_BUFLEN; + freebuf = VOICE_CAPTURE_BUFLEN - elemInFifo; + + IO_MIC_UNLOCK(); + + return freebuf; +} + +int io_mic_fifo_usedPercent() +{ + int fs = io_mic_fifo_freespace(); + int used = VOICE_CAPTURE_BUFLEN - fs; + used = (used * 100) / VOICE_CAPTURE_BUFLEN; + return used; +} + +void io_ls_write_fifo_clear() +{ + io_ls_wridx = io_ls_rdidx = 0; +} + +int io_ls_fifo_freespace(int nolock) +{ + int freebuf = 0; + + if (nolock == 0) IO_LS_LOCK; + + int elemInFifo = (io_ls_wridx + VOICE_PLAYBACK_BUFLEN - io_ls_rdidx) % VOICE_PLAYBACK_BUFLEN; + freebuf = VOICE_PLAYBACK_BUFLEN - elemInFifo; + + if (nolock == 0) IO_LS_UNLOCK(); + + //printf("fifolen:%d check: pbw:%d pbr:%d freebuf:%d\n",VOICE_PLAYBACK_BUFLEN,io_ls_wridx,io_ls_rdidx,freebuf); + + return freebuf; +} + +int io_ls_fifo_usedspace() +{ + int anz = io_ls_fifo_freespace(0); + return VOICE_PLAYBACK_BUFLEN - anz; +} + +void io_ls_write_fifo(float sample) +{ + IO_LS_LOCK; + + // check if there is free space in fifo + if (io_ls_fifo_freespace(1) == 0) + { + IO_LS_UNLOCK(); + printf("************* LS fifo full\n"); + return; + } + + io_ls_buffer[io_ls_wridx] = sample; + if (++io_ls_wridx >= VOICE_PLAYBACK_BUFLEN) io_ls_wridx = 0; + IO_LS_UNLOCK(); +} + +// read num elements +// if num elems not avail, return 0 +int io_ls_read_fifo_num(float* data, int num) +{ + IO_LS_LOCK; + + int elemInFifo = (io_ls_wridx + VOICE_PLAYBACK_BUFLEN - io_ls_rdidx) % VOICE_PLAYBACK_BUFLEN; + + if (elemInFifo < num) + { + // Fifo empty, no data available + //printf("only %d elements available\n", elemInFifo); + IO_LS_UNLOCK(); + return 0; + } + + for (int i = 0; i < num; i++) + { + *data++ = io_ls_buffer[io_ls_rdidx]; + if (++io_ls_rdidx >= VOICE_PLAYBACK_BUFLEN) io_ls_rdidx = 0; + } + IO_LS_UNLOCK(); + + return 1; +} + +void io_clear_voice_fifos() +{ + io_ls_write_fifo_clear(); + io_mic_write_fifo_clear(); +} diff --git a/hsmodem/hsmodem.cpp b/hsmodem/hsmodem.cpp index d08cd28..6f0f973 100755 --- a/hsmodem/hsmodem.cpp +++ b/hsmodem/hsmodem.cpp @@ -76,7 +76,6 @@ int keeprunning = 1; // UDP I/O int BC_sock_AppToModem = -1; int DATA_sock_AppToModem = -1; -//int DATA_sock_from_GR = -1; int DATA_sock_FFT_from_GR = -1; int DATA_sock_I_Q_from_GR = -1; @@ -102,12 +101,16 @@ int txinterpolfactor = 20; int rxPreInterpolfactor = 5; int linespeed = 4410; -int captureDeviceNo = -1; -int playbackDeviceNo = -1; -int MicDeviceNo = -1; -int LSDeviceNo = -1; -int initialPBvol = -1; -int initialCAPvol = -1; +char captureDeviceName[101] = { 0 }; +char playbackDeviceName[101] = { 0 }; +char micDeviceName[101] = { 0 }; +char lsDeviceName[101] = { 0 }; + +float softwareCAPvolume = 1; +float softwarePBvolume = 1; +float softwareMICvolume = 1; +float softwareLSvolume = 1; + int announcement = 0; int VoiceAudioMode = VOICEMODE_OFF; int codec = 1; // 0=opus, 1=codec2 @@ -174,19 +177,10 @@ int main(int argc, char* argv[]) } } #endif - init_packer(); initFEC(); init_fft(); - init_voiceproc(); - - /*int ar = init_audio(playbackDeviceNo, captureDeviceNo); - if (ar == -1) - { - keeprunning = 0; - exit(0); - }*/ // start udp RX to listen for broadcast search message from Application UdpRxInit(&BC_sock_AppToModem, UdpBCport_AppToModem, &bc_rxdata, &keeprunning); @@ -194,9 +188,6 @@ int main(int argc, char* argv[]) // start udp RX for data from application UdpRxInit(&DATA_sock_AppToModem, UdpDataPort_AppToModem, &appdata_rxdata, &keeprunning); - // start udp RX to listen for data from GR Receiver - //UdpRxInit(&DATA_sock_from_GR, UdpDataPort_fromGR, &GRdata_rxdata, &keeprunning); - printf("QO100modem initialised and running\n"); while (keeprunning) @@ -206,17 +197,15 @@ int main(int argc, char* argv[]) startModem(); restart_modems = 0; } - + //doArraySend(); if (VoiceAudioMode == VOICEMODE_INTERNALLOOP) { // loop voice mic to LS float f; - if (cap_read_fifo_voice(&f)) + if (io_mic_read_fifo(&f)) { - if(softwareCAPvolume_voice >= 0) - f *= softwareCAPvolume_voice; - pb_write_fifo_voice(f); + io_ls_write_fifo(f); } } @@ -224,30 +213,29 @@ int main(int argc, char* argv[]) { // send mic to codec float f; - if (cap_read_fifo_voice(&f)) + if (io_mic_read_fifo(&f)) { - if (softwareCAPvolume_voice >= 0) - f *= softwareCAPvolume_voice; encode(f); } } - + // demodulate incoming audio data stream static int old_tm = 0; int tm = getus(); if (tm >= (old_tm + 1000000)) { // read Audio device list every 1s - readAudioDevices(); + io_readAudioDevices(); old_tm = tm; } - int dret = demodulator(); if (dret == 0) { // no new data in fifo // not important how long to sleep, 10ms is fine +#ifdef _LINUX_ sleep_ms(10); +#endif } } printf("stopped: %d\n", keeprunning); @@ -301,28 +289,29 @@ void startModem() // int TX audio and modulator close_dsp(); - init_audio_result = init_audio(playbackDeviceNo, captureDeviceNo); - setPBvolume(initialPBvol); - setCAPvolume(initialCAPvol); + init_audio_result = io_init_sound(playbackDeviceName, captureDeviceName); init_dsp(); } -void setAudioDevices(int pb, int cap, int pbvol, int capvol, int announce, int pbls, int pbmic) +void io_setAudioDevices(uint8_t pbvol, uint8_t capvol, uint8_t announce, uint8_t pbls, uint8_t pbmic, char *pbname, char*capname) { - //printf("%d %d\n", pb, cap); - - if (pb != playbackDeviceNo || cap != captureDeviceNo) - { - restart_modems = 1; - playbackDeviceNo = pb; - captureDeviceNo = cap; - initialPBvol = pbvol; - initialCAPvol = capvol; - initialLSvol = pbls; - initialMICvol = pbmic; - } + io_setPBvolume(pbvol); + io_setCAPvolume(capvol); + io_setLSvolume(pbls); + io_setMICvolume(pbmic); announcement = announce; + + if (strcmp(pbname, playbackDeviceName) || strcmp(captureDeviceName,capname)) + { + restart_modems = 1; + + snprintf(playbackDeviceName, 100, "%s", pbname); + playbackDeviceName[99] = 0; + + snprintf(captureDeviceName, 100, "%s", capname); + captureDeviceName[99] = 0; + } } // called from UDP RX thread for Broadcast-search from App @@ -330,7 +319,22 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) { if (len > 0 && pdata[0] == 0x3c) { - setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], pdata[6], pdata[7]); + /* searchmodem message received + * Format: + * Byte : + * 0 ... 0x3c + * 1 ... PB volume + * 2 ... CAP volume + * 3 ... announcement on / off, duration + * 4 ... DV loudspeaker volume + * 5 ... DV mic volume + * 6..9 ... unused + * 10 .. 109 ... PB device name + * 110 .. 209 ... CAP device name + */ + + //printf("%d %d %d %d %d %d %d \n",pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], pdata[6], pdata[7]); + io_setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], (char *)(pdata + 10), (char *)(pdata + 110)); char rxip[20]; strcpy(rxip, inet_ntoa(rxsock->sin_addr)); @@ -347,7 +351,7 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) // App searches for the modem IP, mirror the received messages // so the app gets an UDP message with this local IP int alen; - uint8_t* txdata = getAudioDevicelist(&alen); + uint8_t* txdata = io_getAudioDevicelist(&alen); sendUDP(appIP, UdpDataPort_ModemToApp, txdata, alen); } else @@ -360,7 +364,7 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) // App searches for the modem IP, mirror the received messages // so the app gets an UDP message with this local IP int alen; - uint8_t* txdata = getAudioDevicelist(&alen); + uint8_t* txdata = io_getAudioDevicelist(&alen); sendUDP(appIP, UdpDataPort_ModemToApp, txdata, alen); } } @@ -432,14 +436,14 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) if (type == 21) { // set playback volume (in % 0..100) - setVolume(0,minfo); + io_setVolume(0,minfo); return; } if (type == 22) { // set capture volume (in % 0..100) - setVolume(1,minfo); + io_setVolume(1,minfo); return; } @@ -459,16 +463,35 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) if (type == 25) { - //printf("%d %d %d %d %d\n", pdata[0], pdata[1], pdata[2], pdata[3], pdata[4]); - LSDeviceNo = pdata[1]; - MicDeviceNo = pdata[2]; - VoiceAudioMode = pdata[3]; - codec = pdata[4]; + /* + * Format: + * 0 ... statics.SetVoiceMode (25) + * 1 ... voicemode + * 2 ... codec + * 3-102 ... LS device name + * 103-202 ... MIC device name + */ + memcpy(lsDeviceName, pdata + 3, 100); + lsDeviceName[99] = 0; + memcpy(micDeviceName, pdata + 103, 100); + micDeviceName[99] = 0; + + VoiceAudioMode = pdata[1]; + codec = pdata[2]; + + printf("LS:<%s> MIC:<%s> Mode:%d codec:%d\n", lsDeviceName, micDeviceName, VoiceAudioMode, codec); // init voice audio - init_voice_result = init_audio_voice(LSDeviceNo, MicDeviceNo); - init_voiceproc(); - + if (VoiceAudioMode == 0) + { + close_voiceproc(); + io_close_voice(); + } + else + { + init_voice_result = io_init_voice(lsDeviceName, micDeviceName); + init_voiceproc(); + } return; } @@ -492,7 +515,7 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) { // this is the first frame of a larger file sendAnnouncement(); - // send it multiple times, like a preamble, to give the + // send first frame multiple times, like a preamble, to give the // receiver some time for synchronisation // caprate: samples/s. This are symbols: caprate/txinterpolfactor // and bits: symbols * bitsPerSymbol diff --git a/hsmodem/hsmodem.h b/hsmodem/hsmodem.h index 958a7ea..161d8cf 100755 --- a/hsmodem/hsmodem.h +++ b/hsmodem/hsmodem.h @@ -33,9 +33,8 @@ #define _USE_MATH_DEFINES #include -#pragma comment(lib, "bass.lib") -#pragma comment(lib, "basswasapi.lib") #pragma comment(lib, "libliquid.lib") +#pragma comment(lib, "libsoundio.lib") #pragma comment(lib, "fftw_lib/libfftw3-3.lib") #pragma comment(lib, "opus.lib") #pragma comment(lib, "libcodec2.lib") @@ -57,15 +56,13 @@ #endif #include "opus.h" -#include "bass.h" -#include "basswasapi.h" #include "liquid.h" #include "frameformat.h" #include "fec.h" #include "udp.h" #include "symboltracker.h" -#include "bassenc_opus.h" #include "codec2.h" +#include "soundio.h" #define jpg_tempfilename "rxdata.jpg" @@ -74,7 +71,7 @@ #define CRC16FILE 2 // definitions for audio -#define MAXDEVSTRLEN 2000 +#define MAXDEVSTRLEN 5000 #define CHANNELS 1 // no of channels used // voice audio sampling rate @@ -120,22 +117,26 @@ void initFEC(); void GetFEC(uint8_t* txblock, int len, uint8_t* destArray); int cfec_Reconstruct(uint8_t* darr, uint8_t* destination); -int init_audio(int pbdev, int capdev); -int pb_fifo_freespace(int nolock); -int pb_fifo_usedspace(); -void pb_write_fifo_clear(); -void pb_write_fifo(float sample); -int cap_read_fifo(float* data); -uint8_t* getAudioDevicelist(int* len); -void setPBvolume(int v); -void setCAPvolume(int v); -void setVolume(int pbcap, int v); +void io_pb_write_fifo_clear(); +int io_init_sound(char* pbname, char* capname); +int io_pb_fifo_freespace(int nolock); +void io_init_pipes(); +void io_clear_audio_fifos(); +void io_close_audio(); +int io_cap_read_fifo(float* data); +void io_readAudioDevices(); +uint8_t* io_getAudioDevicelist(int* len); +void io_pb_write_fifo(float sample); +int io_pb_fifo_usedspace(); +int io_cap_fifo_usedPercent(); +int io_pb_read_fifo_num(float* data, int num); +void io_clear_audio_fifos(); +void io_setPBvolume(int v); +void io_setCAPvolume(int v); +void io_setVolume(int pbcap, int v); + void setVolume_voice(int pbcap, int v); -int init_wasapi(int pbdev, int capdev); void sendAnnouncement(); -void readAudioDevices(); -void clear_audio_fifos(); -void clear_voice_fifos(); void sleep_ms(int ms); int getus(); @@ -143,7 +144,7 @@ void GRdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock); void toGR_sendData(uint8_t* data, int type, int status); void modulator(uint8_t sym_in); -int pb_fifo_usedBlocks(); +int io_pb_fifo_usedBlocks(); void init_dsp(); int demodulator(); void sendToModulator(uint8_t* d, int len); @@ -151,32 +152,34 @@ void resetModem(); void close_dsp(); void init_fft(); void exit_fft(); -void showbytestringf(char* title, float* data, int anz); +void showbytestringf(char* title, float* data, int totallen, int anz); uint16_t* make_waterfall(float fre, int* retlen); -int init_audio_voice(int setpbdev, int setcapdev); -void pb_write_fifo_voice(float sample); -int cap_read_fifo_voice(float* data); -void toVoice(float sample); void toCodecDecoder(uint8_t* pdata, int len); void init_voiceproc(); void encode(float f); -int init_wasapi_voice(int pbdev, int capdev); void init_codec2(); void encode_codec2(float f); void toCodecDecoder_codec2(uint8_t* pdata, int len); -void close_wasapi(); -void close_wasapi_voice(); void closeAllandTerminate(); void close_voiceproc(); void close_codec2(); -void close_audio(); -void close_audio_voice(); -int cap_fifo_usedPercent(); +void io_voice_init_pipes(); +int io_mic_read_fifo(float* data); +void io_ls_write_fifo(float sample); +void io_setLSvolume(int v); +void io_setMICvolume(int v); +char* getDevID(char* devname, int io); +int io_init_voice(char* lsname, char* micname); +int min_int(int a, int b); +void io_close_voice(); +int io_ls_read_fifo_num(float* data, int num); +void io_mic_write_fifo(float sample); +void write_sample_s16ne(char* ptr, double sample); void km_symtrack_cccf_create(int _ftype, unsigned int _k, @@ -187,6 +190,7 @@ void km_symtrack_cccf_reset(int mode); void km_symtrack_cccf_set_bandwidth(float _bw); void km_symtrack_execute(liquid_float_complex _x, liquid_float_complex* _y, unsigned int* _ny, unsigned int* psym_out); + extern int speedmode; extern int bitsPerSymbol; extern int constellationSize; @@ -200,7 +204,7 @@ extern int txinterpolfactor; extern int rxPreInterpolfactor; extern char appIP[20]; extern float softwareCAPvolume; -extern float softwareCAPvolume_voice; +extern float softwarePBvolume; extern int announcement; extern int ann_running; extern int transmissions; @@ -216,13 +220,8 @@ extern int codec; extern int trigger_resetmodem; extern int rxlevel_deteced; extern int rx_in_sync; - -// audio device description table -typedef struct { - int bassdev; // bass (basswasapi) dev no - char name[256]; // DEV name - char id[256]; -} AUDIODEVS; +extern float softwareMICvolume; +extern float softwareLSvolume; #ifdef _LINUX_ int isRunning(char* prgname); diff --git a/hsmodem/hsmodem.sh b/hsmodem/hsmodem.sh index 07158c2..bf313f0 100755 --- a/hsmodem/hsmodem.sh +++ b/hsmodem/hsmodem.sh @@ -21,11 +21,16 @@ git clone https://github.com/dj0abr/SSB_HighSpeed_Modem echo echo "Compile the sources and build the executable program. Press ENTER ..." read +pwd +cd SSB_HighSpeed_Modem/hsmodem +pwd make -j 4 echo echo "copy the shared libraries to it's final location. Press ENTER ..." read -echo +echo copy oscardata.exe +pwd +cp ../oscardata/oscardata/bin/Release/oscardata.exe ../hsmodemLinux # now find the shared library directory # this is the directory where libopus.so is installed LIBNAME=$(find /usr -name libopus.so | head -1) @@ -36,9 +41,15 @@ echo if [ ${ARCHITECTURE} == 'x86_64' ]; then sudo cp ./SharedLibs/$ARCHITECTURE/*.so $LIBFOLDER +echo "finished. Your project is in folder: ./SSB_HighSpeed_Modem/hsmodemLinux" +echo "you can copy this folder to any location" +echo "to run hsmodem: mono oscardata.exe" elif [ ${ARCHITECTURE} == 'aarch64' ]; then sudo cp ./SharedLibs/$ARCHITECTURE/*.so $LIBFOLDER +echo "finished. Your project is in folder: ./SSB_HighSpeed_Modem/hsmodemLinux" +echo "you can copy this folder to any location" +echo "to run hsmodem: mono oscardata.exe" else echo ================================================================ echo error: no shared libs for $ARCHITECTURE . Install them manually. diff --git a/hsmodem/hsmodem.vcxproj b/hsmodem/hsmodem.vcxproj index ad9e7de..9a005a5 100755 --- a/hsmodem/hsmodem.vcxproj +++ b/hsmodem/hsmodem.vcxproj @@ -131,6 +131,8 @@ true wsock32.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;%(AdditionalDependencies) /NODEFAULTLIB:libcmt.lib %(AdditionalOptions) + + @@ -226,6 +228,7 @@ + @@ -235,27 +238,29 @@ + - - - - + + + + + diff --git a/hsmodem/hsmodem.vcxproj.filters b/hsmodem/hsmodem.vcxproj.filters index f9c6313..72c6c2c 100755 --- a/hsmodem/hsmodem.vcxproj.filters +++ b/hsmodem/hsmodem.vcxproj.filters @@ -39,9 +39,6 @@ Source Files - - Source Files - Source Files @@ -51,22 +48,28 @@ Source Files - - Source Files - Source Files - - Source Files - Source Files - + Source Files - + + Source Files + + + Source Files + + + Source Files + + + Source Files + + Source Files @@ -119,5 +122,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/hsmodem/libsoundio.a b/hsmodem/libsoundio.a new file mode 100644 index 0000000..e71c053 Binary files /dev/null and b/hsmodem/libsoundio.a differ diff --git a/hsmodem/libsoundio.lib b/hsmodem/libsoundio.lib new file mode 100755 index 0000000..965fb95 Binary files /dev/null and b/hsmodem/libsoundio.lib differ diff --git a/hsmodem/liquid_if.cpp b/hsmodem/liquid_if.cpp index 9d3514f..6550e48 100755 --- a/hsmodem/liquid_if.cpp +++ b/hsmodem/liquid_if.cpp @@ -37,7 +37,7 @@ void close_modulator(); void init_dsp() { init_modulator(); - pb_write_fifo_clear(); + io_pb_write_fifo_clear(); init_demodulator(); } @@ -197,13 +197,13 @@ void modulator(uint8_t sym_in) int fs; while(1) { - fs = pb_fifo_freespace(0); + fs = io_pb_fifo_freespace(0); // wait until there is space in fifo if(fs) break; sleep_ms(10); } - pb_write_fifo(usb * 0.2f); // reduce volume and send to soundcard + io_pb_write_fifo(usb * 0.2f); // reduce volume and send to soundcard } } @@ -280,11 +280,11 @@ void make_FFTdata(float f) int bidx = 0; txpl[bidx++] = 4; // type 4: FFT data follows - int us = pb_fifo_usedBlocks(); + int us = io_pb_fifo_usedBlocks(); if (us > 255 || ann_running == 1) us = 255; txpl[bidx++] = us; // usage of TX fifo - us = cap_fifo_usedPercent(); + us = io_cap_fifo_usedPercent(); if (us > 255) us = 255; txpl[bidx++] = us; // usage of TX fifo @@ -338,9 +338,13 @@ static int ccol_idx = 0; // get one received sample float f; - int ret = cap_read_fifo(&f); + int ret = io_cap_read_fifo(&f); if(ret == 0) return 0; + if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN) + { + io_ls_write_fifo(f); + } // input volume f *= softwareCAPvolume; diff --git a/hsmodem/main_helper.cpp b/hsmodem/main_helper.cpp index e7efece..bfb8329 100755 --- a/hsmodem/main_helper.cpp +++ b/hsmodem/main_helper.cpp @@ -74,14 +74,8 @@ void closeAllandTerminate() // terminate all Threads keeprunning = 0; // close audio -#ifdef _LINUX_ - close_audio(); - close_audio_voice(); -#endif -#ifdef _WIN32_ - close_wasapi(); - close_wasapi_voice(); -#endif + io_close_audio(); + io_close_voice(); // close fft exit_fft(); // close codec2 and opus @@ -122,9 +116,9 @@ void showbytestring16(char *title, uint16_t *data, int anz) printf("\n"); } -void showbytestringf(char* title, float* data, int anz) +void showbytestringf(char* title, float* data, int totallen, int anz) { - printf("%s. Len %d: ", title, anz); + printf("%s. Len %d: ", title, totallen); for (int i = 0; i < anz; i++) printf("%7.4f ", data[i]); printf("\n"); diff --git a/hsmodem/prepare_ubuntu b/hsmodem/prepare_ubuntu new file mode 100644 index 0000000..b1e1d55 --- /dev/null +++ b/hsmodem/prepare_ubuntu @@ -0,0 +1,10 @@ +echo This script installs packages required to build and run hsmodem +echo +echo ATTENTION ! These libraries must be installed manually according to your system +echo libbass.so, libbassopus.so, libbassenc.so +echo copy it to /usr/lib, /usr/local/lib or whereever your system expects them +echo you find them at: https://www.un4seen.com/ +echo Press ENTER to continue +echo +sudo apt-get update +sudo apt-get -y install libopus-dev libfftw3-dev libcodec2-dev libsndfile-dev libasound-dev mono-complete pavucontrol diff --git a/hsmodem/soundio.cpp b/hsmodem/soundio.cpp new file mode 100755 index 0000000..bf8822b --- /dev/null +++ b/hsmodem/soundio.cpp @@ -0,0 +1,665 @@ +/* +* High Speed modem to transfer data in a 2,7kHz SSB channel +* ========================================================= +* Author: DJ0ABR +* +* (c) DJ0ABR +* www.dj0abr.de +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* soundio.c ... interface to libsoundio +* +*/ + +#include "hsmodem.h" + +void io_cap_write_fifo(float sample); + +#define MAXAUDIODEVICES 50 + +struct SoundIo* soundio = NULL; +struct SoundIoDevice* io_pb_device = NULL; +struct SoundIoDevice* io_cap_device = NULL; +struct SoundIoInStream* instream = NULL; +struct SoundIoOutStream* outstream = NULL; + + +typedef struct _AUDIODEV_ { + int in_out = 0; // 0=in, 1=out + char name[1000] = { 0 }; + char id[1000] = { 0 }; + int minsamprate = 44100; + int maxsamprate = 48000; + int stereo_mono = 2; // 1=mono, 2=stereo +} AUDIODEV; + +AUDIODEV audiodev[MAXAUDIODEVICES]; +int audiodevidx = 0; + +void print_devs() +{ + printf("\n ==== AUDIO devices ====\n"); + for (int i = 0; i < audiodevidx; i++) + { + if(i>0) printf(" -----------------\n"); + printf("Name: %s\n", audiodev[i].name); + printf("ID : %s\n", audiodev[i].id); + printf("I/O : %s\n", (audiodev[i].in_out == 0) ? "record":"playback"); + printf("Chan: %s\n", (audiodev[i].stereo_mono == 2) ? "stereo" : "mono"); + printf("minR: %d\n", audiodev[i].minsamprate); + printf("maxR: %d\n", audiodev[i].maxsamprate); + } + printf("\n =======================\n"); +} + +static void get_channel_layout(const struct SoundIoChannelLayout* layout) +{ + if (layout->name) + { + if (strstr(layout->name, "ereo")) + audiodev[audiodevidx].stereo_mono = 2; + if (strstr(layout->name, "ono")) + audiodev[audiodevidx].stereo_mono = 1; + } +} + +int print_device(struct SoundIoDevice* device) +{ + if (!device->probe_error) + { +/*#ifdef _WIN32_ + // only use raw (exclusive) devices + if (device->is_raw == false) return 0; +#endif*/ + + // ignore if exists + for (int i = 0; i < audiodevidx; i++) + if (!strcmp(device->id, audiodev[i].id)) return 0; + + if (strstr(device->name, "onitor")) return 0; + + strncpy(audiodev[audiodevidx].id, device->id, 999); + audiodev[audiodevidx].id[999] = 0; + strncpy(audiodev[audiodevidx].name, device->name, 999); + audiodev[audiodevidx].name[999] = 0; + + for (int i = 0; i < device->layout_count; i++) + get_channel_layout(&device->layouts[i]); + + for (int i = 0; i < device->sample_rate_count; i++) + { + struct SoundIoSampleRateRange* range = &device->sample_rates[i]; + if (range->min < audiodev[audiodevidx].minsamprate) + audiodev[audiodevidx].minsamprate = range->min; + + if (range->max > audiodev[audiodevidx].maxsamprate) + audiodev[audiodevidx].maxsamprate = range->max; + } + if (audiodev[audiodevidx].minsamprate > 44100) + return 0; + if (audiodev[audiodevidx].maxsamprate < 48000) + return 0; + return 1; + } + return 0; +} + +static int scan_devices(struct SoundIo* soundio) +{ + audiodevidx = 0; + for (int i = 0; i < soundio_input_device_count(soundio); i++) + { + + struct SoundIoDevice* device = soundio_get_input_device(soundio, i); + if (print_device(device) == 1) + { + audiodev[audiodevidx].in_out = 0; + audiodevidx++; + } + soundio_device_unref(device); + } + + for (int i = 0; i < soundio_output_device_count(soundio); i++) + { + struct SoundIoDevice* device = soundio_get_output_device(soundio, i); + if (print_device(device) == 1) + { + audiodev[audiodevidx].in_out = 1; + audiodevidx++; + } + soundio_device_unref(device); + } + return 0; +} + +// build string of audio device name, to be sent to application as response to Broadcast search +// starting with PB devices, sperarator ^, capture devices +// separator between devices: ~ +uint8_t io_devstring[MAXDEVSTRLEN + 100]; + +void io_buildUdpAudioList() +{ + memset(io_devstring, 0, sizeof(io_devstring)); + io_devstring[0] = ' '; // placeholder for ID for this UDP message + io_devstring[1] = '0' + init_audio_result; + io_devstring[2] = '0' + init_voice_result; + + // playback devices + for (int i = 0; i < audiodevidx; i++) + { + if (audiodev[i].in_out == 1) + { + strcat((char*)io_devstring, audiodev[i].name); + strcat((char*)io_devstring, "~"); // audio device separator + } + } + + strcat((char*)(io_devstring + 1), "^"); // PB, CAP separator + + // capture devices + for (int i = 0; i < audiodevidx; i++) + { + if (audiodev[i].in_out == 0) + { + strcat((char*)io_devstring, audiodev[i].name); + strcat((char*)io_devstring, "~"); // audio device separator + } + } + + io_devstring[0] = 3; // ID for this UDP message +} + +uint8_t* io_getAudioDevicelist(int* len) +{ + // update Status + io_devstring[1] = '0' + init_audio_result; + io_devstring[2] = '0' + init_voice_result; + + *len = strlen((char*)(io_devstring + 1)) + 1; + return io_devstring; +} + +void io_readAudioDevices() +{ + if (soundio == NULL) return; + // to get actual data + soundio_flush_events(soundio); + + scan_devices(soundio); // read devices + io_buildUdpAudioList(); + + //print_devs(); +} + +char* getDevID(char* devname, int io) +{ + for (int i = 0; i < audiodevidx; i++) + { + if (!strcmp(devname, audiodev[i].name) && io == audiodev[i].in_out) + { + return audiodev[i].id; + } + } + return NULL; +} + +int min_int(int a, int b) +{ + return (a < b) ? a : b; +} + +void read_callback(struct SoundIoInStream* instream, int frame_count_min, int frame_count_max) +{ + + int err; + //printf("cap: %d %d\n", frame_count_min, frame_count_max); + //int chans = instream->layout.channel_count; + + struct SoundIoChannelArea* areas; + // samples are in areas.ptr + int frames_left = frame_count_max; // take all + while (1) + { + int frame_count = frames_left; + if ((err = soundio_instream_begin_read(instream, &areas, &frame_count))) + { + fprintf(stderr, "begin read error: %s", soundio_strerror(err)); + exit(1); + } + if (!frame_count) + break; + + for (int frame = 0; frame < frame_count; frame += 1) + { + for (int ch = 0; ch < instream->layout.channel_count; ch += 1) + { + int16_t rxdata; + memcpy(&rxdata, areas[ch].ptr, instream->bytes_per_sample); + areas[ch].ptr += areas[ch].step; + if (ch == 0) + { + float f = rxdata; + f /= 32768; + f *= softwareCAPvolume; + io_cap_write_fifo(f); + } + } + } + + //measure_speed_bps(frame_count); + + if ((err = soundio_instream_end_read(instream))) + { + fprintf(stderr, "end read error: %s", soundio_strerror(err)); + exit(1); + } + + frames_left -= frame_count; + if (frames_left <= 0) + break; + } +} +/* +void read_callback(struct SoundIoInStream* instream, int frame_count_min, int frame_count_max) +{ + int err; + //printf("cap: %d %d\n", frame_count_min, frame_count_max); + // bytes_per_frame == 4 because we use float + // instream->bytes_per_sample/bytes_per_frame = 1 (mono) or 2 (stereo) + int chans = instream->layout.channel_count; + + struct SoundIoChannelArea* areas; + // samples are in areas.ptr + int frames_left = frame_count_max; // take all + while (1) + { + int frame_count = frames_left; + if ((err = soundio_instream_begin_read(instream, &areas, &frame_count))) + { + fprintf(stderr, "begin read error: %s", soundio_strerror(err)); + exit(1); + } + if (!frame_count) + break; + + // do something with the data in *area.ptr + // take a float every chans*4 Bytes + int16_t* samples = (int16_t*)(areas[0].ptr); + int pos = 0; + for (int i = 0; i < frame_count; i++) + { + float f = samples[pos]; + f /= 32768; + f *= softwareCAPvolume; + io_cap_write_fifo(f); + pos += chans; + } + + //measure_speed_bps(frame_count); + + if ((err = soundio_instream_end_read(instream))) { + fprintf(stderr, "end read error: %s", soundio_strerror(err)); + exit(1); + } + + frames_left -= frame_count; + if (frames_left <= 0) + break; + } +} +*/ +void overflow_callback(struct SoundIoInStream* instream) +{ + static int count = 0; + printf("overflow %d\n", ++count); +} + +#define MAXCAPCHUNKLEN 50000 + +static void write_callback(struct SoundIoOutStream* outstream, int frame_count_min, int frame_count_max) +{ + struct SoundIoChannelArea* areas; + int err; + int frames_left = frame_count_max; + + while (1) + { + int frame_count = frames_left; + if ((err = soundio_outstream_begin_write(outstream, &areas, &frame_count))) + { + fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err)); + exit(1); + } + + if (!frame_count) + break; + + float f[MAXCAPCHUNKLEN]; + int fiforet = io_pb_read_fifo_num(f, frame_count); + if (fiforet == 0) + { + // elements not available, fill with zeroes + //printf("not enough data, send zeroes\n"); + memset(f, 0, sizeof(float) * frame_count); + } + + const struct SoundIoChannelLayout* layout = &outstream->layout; + + for (int frame = 0; frame < frame_count; frame++) + { + for (int channel = 0; channel < layout->channel_count; channel++) + { + write_sample_s16ne(areas[channel].ptr, f[frame]); + areas[channel].ptr += areas[channel].step; + } + } + + if ((err = soundio_outstream_end_write(outstream))) { + if (err == SoundIoErrorUnderflow) + return; + fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err)); + exit(1); + } + + frames_left -= frame_count; + if (frames_left <= 0) + break; + } +} +/* +static void write_callback(struct SoundIoOutStream* outstream, int frame_count_min, int frame_count_max) +{ + int chans = outstream->layout.channel_count; + struct SoundIoChannelArea* areas; + int err; + int frames_left = min_int(frame_count_max,MAXCAPCHUNKLEN);// frame_count_max; + //printf("\nmin: %d max:%d\n", frame_count_min, frame_count_max); + + // we have to write frame_count_max, not less, or we get an underrun + // this has to be written in chunks requested by soundio_outstream_begin_write + float f[MAXCAPCHUNKLEN]; + while (1) + { + int frame_count = frames_left; + if ((err = soundio_outstream_begin_write(outstream, &areas, &frame_count))) { + printf("unrecoverable soundio_outstream_begin_write error: %s\n", soundio_strerror(err)); + exit(1); + } + if (!frame_count) break; // will normally never happen + //printf("chunk: %d\n", frame_count); + + // soundio_outstream_begin_write requested to write frame_count elements + int fiforet = io_pb_read_fifo_num(f, frame_count); + if (fiforet == 0) + { + // elements not available, fill with zeroes + //printf("not enough data, send zeroes\n"); + memset(f, 0, sizeof(float) * frame_count); + } + + // apply volume + for (int i = 0; i < frame_count; i++) + f[i] *= softwarePBvolume; + + // put data into soundio buffer + for (int frame = 0; frame < frame_count; frame++) + { + for (int ch = 0; ch < chans; ch++) + { + int16_t* s = (int16_t*)areas[ch].ptr; + *s = (int16_t)(f[frame] * 32768.0); + areas[ch].ptr += areas[ch].step; + } + } + + // and finalize this chunk + if ((err = soundio_outstream_end_write(outstream))) { + if (err == SoundIoErrorUnderflow) + return; + printf("unrecoverable soundio_outstream_end_write error: %s\n", soundio_strerror(err)); + exit(1); + } + + frames_left -= frame_count; + if (frames_left <= 0) + break; + } +} +*/ +void underflow_callback(struct SoundIoOutStream* outstream) +{ + static int count = 0; + printf("underflow %d\n", count++); +} + + +int io_init_sound(char *pbname, char *capname) +{ + int err; + init_audio_result = 0; + + printf("\n ==== IO INIT AUDIO devices ====\n"); + printf("requested: <%s> <%s>\ncapture rate:%d\n",pbname,capname,caprate); + + io_close_audio(); + + // prepare and connect to libsoundio + soundio = soundio_create(); + if (!soundio) { + printf("soundio_create: out of memory\n"); + return 0; + } +#ifdef _WIN32_ + if ((err=soundio_connect_backend(soundio, SoundIoBackendWasapi))) { + printf("soundio_connect: %s\n", soundio_strerror(err)); + return 0; + } +#endif +#ifdef _LINUX_ + if ((err = soundio_connect(soundio))) { + printf("soundio_connect: %s\n", soundio_strerror(err)); + return 0; + } +#endif + + io_readAudioDevices(); + io_init_pipes(); + + if (pbname == NULL || capname == NULL || strlen(pbname) < 3 || strlen(capname) < 3) // no devices defined yet + { + printf("no devices specified\n"); + return 0; + } + + char* pbdevid = getDevID(pbname,1); + if (pbdevid == NULL) return 0; + + char* capdevid = getDevID(capname,0); + if (capdevid == NULL) return 0; + + // define the capture device + printf("selected CAP device:\nname:%s\nid :%s\n", capname, capdevid); + + soundio_flush_events(soundio); + + for (int i = 0; i < soundio_input_device_count(soundio); i++) + { + io_cap_device = NULL; + struct SoundIoDevice* device = soundio_get_input_device(soundio, i); + if (strcmp(device->id, capdevid) == 0 +#ifdef _WIN32_ + && device->is_raw == true +#endif + ) + { + io_cap_device = device; + break; + } + soundio_device_unref(device); + } + if (!io_cap_device) + { + printf("Invalid device id: %s\n", capdevid); + return 0; + } + + if (io_cap_device->probe_error) + { + printf("Unable to probe device: %s\n", soundio_strerror(io_cap_device->probe_error)); + return 0; + } + + // create capture callback + instream = soundio_instream_create(io_cap_device); + if (!instream) { + printf("out of memory\n"); + return 0; + } + + instream->format = SoundIoFormatS16NE; + instream->sample_rate = caprate; + instream->software_latency = 0.0; + instream->read_callback = read_callback; + instream->overflow_callback = overflow_callback; + instream->userdata = NULL; + + if ((err = soundio_instream_open(instream))) { + printf("unable to open input stream: %s", soundio_strerror(err)); + return 0; + } + + if ((err = soundio_instream_start(instream))) { + fprintf(stderr, "unable to start input device: %s", soundio_strerror(err)); + return 0; + } + init_audio_result |= 2; + // the CAP callback is running now + + // define the playback device + printf("selected PB device:\nname:%s\nid :%s\n", pbname, pbdevid); + + for (int i = 0; i < soundio_output_device_count(soundio); i++) + { + io_pb_device = NULL; + struct SoundIoDevice* device = soundio_get_output_device(soundio, i); + if (strcmp(device->id, pbdevid) == 0 +#ifdef _WIN32_ + && device->is_raw == true +#endif + ) + { + io_pb_device = device; + break; + } + soundio_device_unref(device); + } + if (!io_pb_device) + { + printf("Invalid device id: %s\n", pbdevid); + return 0; + } + + if (io_pb_device->probe_error) + { + printf("Unable to probe device: %s\n", soundio_strerror(io_pb_device->probe_error)); + return 0; + } + + // create playback callback + outstream = soundio_outstream_create(io_pb_device); + if (!outstream) { + printf("soundio_outstream_create: out of memory\n"); + return 0; + } + + outstream->format = SoundIoFormatS16NE; + outstream->sample_rate = caprate; + outstream->software_latency = 0.0; + outstream->write_callback = write_callback; + outstream->underflow_callback = underflow_callback; + outstream->userdata = NULL; + + if ((err = soundio_outstream_open(outstream))) { + printf("unable to open output stream: %s", soundio_strerror(err)); + return 0; + } + + if ((err = soundio_outstream_start(outstream))) { + fprintf(stderr, "unable to start output device: %s", soundio_strerror(err)); + return 0; + } + init_audio_result |= 1; + + printf("==== Audio init finished: %d ====\n", init_audio_result); + + return init_audio_result; +} + +void io_close_audio() +{ + printf("close Audio\n"); + if(instream) soundio_instream_destroy(instream); + instream = NULL; + + if (outstream) soundio_outstream_destroy(outstream); + outstream = NULL; + + if(io_pb_device) soundio_device_unref(io_pb_device); + io_pb_device = NULL; + + if (io_cap_device) soundio_device_unref(io_cap_device); + io_cap_device = NULL; + + if (soundio) soundio_destroy(soundio); + soundio = NULL; +} + +void io_setPBvolume(int v) +{ + // the volume comes in % 0..99 + softwarePBvolume = ((float)v) / 50.0f; +} + +void io_setCAPvolume(int v) +{ + // the volume comes in % 0..99 + softwareCAPvolume = ((float)v) / 50.0f; +} + +// set volume +void io_setVolume(int pbcap, int v) +{ + if (pbcap == 0) io_setPBvolume(v); + else io_setCAPvolume(v); +} + +void io_setLSvolume(int v) +{ + // the volume comes in % 0..99 + softwareLSvolume = ((float)v) / 50.0f; +} + +void io_setMICvolume(int v) +{ + // the volume comes in % 0..99 + softwareMICvolume = ((float)v) / 50.0f; +} + +void setVolume_voice(int pbcap, int v) +{ + +} + diff --git a/hsmodem/soundio.h b/hsmodem/soundio.h new file mode 100755 index 0000000..71b85ad --- /dev/null +++ b/hsmodem/soundio.h @@ -0,0 +1,1209 @@ +/* + * Copyright (c) 2015 Andrew Kelley + * + * This file is part of libsoundio, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef SOUNDIO_SOUNDIO_H +#define SOUNDIO_SOUNDIO_H + +#include "endian.h" +#include + +/// \cond +#ifdef __cplusplus +#define SOUNDIO_EXTERN_C extern "C" +#else +#define SOUNDIO_EXTERN_C +#endif + +#if defined(SOUNDIO_STATIC_LIBRARY) +# define SOUNDIO_EXPORT SOUNDIO_EXTERN_C +#else +# if defined(_WIN32) +# if defined(SOUNDIO_BUILDING_LIBRARY) +# define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __declspec(dllexport) +# else +# define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __declspec(dllimport) +# endif +# else +# define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __attribute__((visibility ("default"))) +# endif +#endif +/// \endcond + +/** \mainpage + * + * \section intro_sec Overview + * + * libsoundio is a C library for cross-platform audio input and output. It is + * suitable for real-time and consumer software. + * + * Documentation: soundio.h + */ + + +/** \example sio_list_devices.c + * List the available input and output devices on the system and their + * properties. Supports watching for changes and specifying backend to use. + */ + +/** \example sio_sine.c + * Play a sine wave over the default output device. + * Supports specifying device and backend to use. + */ + +/** \example sio_record.c + * Record audio to an output file. + * Supports specifying device and backend to use. + */ + +/** \example sio_microphone.c + * Stream the default input device over the default output device. + * Supports specifying device and backend to use. + */ + +/** \example backend_disconnect_recover.c + * Demonstrates recovering from a backend disconnecting. + */ + +/// See also ::soundio_strerror +enum SoundIoError { + SoundIoErrorNone, + /// Out of memory. + SoundIoErrorNoMem, + /// The backend does not appear to be active or running. + SoundIoErrorInitAudioBackend, + /// A system resource other than memory was not available. + SoundIoErrorSystemResources, + /// Attempted to open a device and failed. + SoundIoErrorOpeningDevice, + SoundIoErrorNoSuchDevice, + /// The programmer did not comply with the API. + SoundIoErrorInvalid, + /// libsoundio was compiled without support for that backend. + SoundIoErrorBackendUnavailable, + /// An open stream had an error that can only be recovered from by + /// destroying the stream and creating it again. + SoundIoErrorStreaming, + /// Attempted to use a device with parameters it cannot support. + SoundIoErrorIncompatibleDevice, + /// When JACK returns `JackNoSuchClient` + SoundIoErrorNoSuchClient, + /// Attempted to use parameters that the backend cannot support. + SoundIoErrorIncompatibleBackend, + /// Backend server shutdown or became inactive. + SoundIoErrorBackendDisconnected, + SoundIoErrorInterrupted, + /// Buffer underrun occurred. + SoundIoErrorUnderflow, + /// Unable to convert to or from UTF-8 to the native string format. + SoundIoErrorEncodingString, +}; + +/// Specifies where a channel is physically located. +enum SoundIoChannelId { + SoundIoChannelIdInvalid, + + SoundIoChannelIdFrontLeft, ///< First of the more commonly supported ids. + SoundIoChannelIdFrontRight, + SoundIoChannelIdFrontCenter, + SoundIoChannelIdLfe, + SoundIoChannelIdBackLeft, + SoundIoChannelIdBackRight, + SoundIoChannelIdFrontLeftCenter, + SoundIoChannelIdFrontRightCenter, + SoundIoChannelIdBackCenter, + SoundIoChannelIdSideLeft, + SoundIoChannelIdSideRight, + SoundIoChannelIdTopCenter, + SoundIoChannelIdTopFrontLeft, + SoundIoChannelIdTopFrontCenter, + SoundIoChannelIdTopFrontRight, + SoundIoChannelIdTopBackLeft, + SoundIoChannelIdTopBackCenter, + SoundIoChannelIdTopBackRight, ///< Last of the more commonly supported ids. + + SoundIoChannelIdBackLeftCenter, ///< First of the less commonly supported ids. + SoundIoChannelIdBackRightCenter, + SoundIoChannelIdFrontLeftWide, + SoundIoChannelIdFrontRightWide, + SoundIoChannelIdFrontLeftHigh, + SoundIoChannelIdFrontCenterHigh, + SoundIoChannelIdFrontRightHigh, + SoundIoChannelIdTopFrontLeftCenter, + SoundIoChannelIdTopFrontRightCenter, + SoundIoChannelIdTopSideLeft, + SoundIoChannelIdTopSideRight, + SoundIoChannelIdLeftLfe, + SoundIoChannelIdRightLfe, + SoundIoChannelIdLfe2, + SoundIoChannelIdBottomCenter, + SoundIoChannelIdBottomLeftCenter, + SoundIoChannelIdBottomRightCenter, + + /// Mid/side recording + SoundIoChannelIdMsMid, + SoundIoChannelIdMsSide, + + /// first order ambisonic channels + SoundIoChannelIdAmbisonicW, + SoundIoChannelIdAmbisonicX, + SoundIoChannelIdAmbisonicY, + SoundIoChannelIdAmbisonicZ, + + /// X-Y Recording + SoundIoChannelIdXyX, + SoundIoChannelIdXyY, + + SoundIoChannelIdHeadphonesLeft, ///< First of the "other" channel ids + SoundIoChannelIdHeadphonesRight, + SoundIoChannelIdClickTrack, + SoundIoChannelIdForeignLanguage, + SoundIoChannelIdHearingImpaired, + SoundIoChannelIdNarration, + SoundIoChannelIdHaptic, + SoundIoChannelIdDialogCentricMix, ///< Last of the "other" channel ids + + SoundIoChannelIdAux, + SoundIoChannelIdAux0, + SoundIoChannelIdAux1, + SoundIoChannelIdAux2, + SoundIoChannelIdAux3, + SoundIoChannelIdAux4, + SoundIoChannelIdAux5, + SoundIoChannelIdAux6, + SoundIoChannelIdAux7, + SoundIoChannelIdAux8, + SoundIoChannelIdAux9, + SoundIoChannelIdAux10, + SoundIoChannelIdAux11, + SoundIoChannelIdAux12, + SoundIoChannelIdAux13, + SoundIoChannelIdAux14, + SoundIoChannelIdAux15, +}; + +/// Built-in channel layouts for convenience. +enum SoundIoChannelLayoutId { + SoundIoChannelLayoutIdMono, + SoundIoChannelLayoutIdStereo, + SoundIoChannelLayoutId2Point1, + SoundIoChannelLayoutId3Point0, + SoundIoChannelLayoutId3Point0Back, + SoundIoChannelLayoutId3Point1, + SoundIoChannelLayoutId4Point0, + SoundIoChannelLayoutIdQuad, + SoundIoChannelLayoutIdQuadSide, + SoundIoChannelLayoutId4Point1, + SoundIoChannelLayoutId5Point0Back, + SoundIoChannelLayoutId5Point0Side, + SoundIoChannelLayoutId5Point1, + SoundIoChannelLayoutId5Point1Back, + SoundIoChannelLayoutId6Point0Side, + SoundIoChannelLayoutId6Point0Front, + SoundIoChannelLayoutIdHexagonal, + SoundIoChannelLayoutId6Point1, + SoundIoChannelLayoutId6Point1Back, + SoundIoChannelLayoutId6Point1Front, + SoundIoChannelLayoutId7Point0, + SoundIoChannelLayoutId7Point0Front, + SoundIoChannelLayoutId7Point1, + SoundIoChannelLayoutId7Point1Wide, + SoundIoChannelLayoutId7Point1WideBack, + SoundIoChannelLayoutIdOctagonal, +}; + +enum SoundIoBackend { + SoundIoBackendNone, + SoundIoBackendJack, + SoundIoBackendPulseAudio, + SoundIoBackendAlsa, + SoundIoBackendCoreAudio, + SoundIoBackendWasapi, + SoundIoBackendDummy, +}; + +enum SoundIoDeviceAim { + SoundIoDeviceAimInput, ///< capture / recording + SoundIoDeviceAimOutput, ///< playback +}; + +/// For your convenience, Native Endian and Foreign Endian constants are defined +/// which point to the respective SoundIoFormat values. +enum SoundIoFormat { + SoundIoFormatInvalid, + SoundIoFormatS8, ///< Signed 8 bit + SoundIoFormatU8, ///< Unsigned 8 bit + SoundIoFormatS16LE, ///< Signed 16 bit Little Endian + SoundIoFormatS16BE, ///< Signed 16 bit Big Endian + SoundIoFormatU16LE, ///< Unsigned 16 bit Little Endian + SoundIoFormatU16BE, ///< Unsigned 16 bit Big Endian + SoundIoFormatS24LE, ///< Signed 24 bit Little Endian using low three bytes in 32-bit word + SoundIoFormatS24BE, ///< Signed 24 bit Big Endian using low three bytes in 32-bit word + SoundIoFormatU24LE, ///< Unsigned 24 bit Little Endian using low three bytes in 32-bit word + SoundIoFormatU24BE, ///< Unsigned 24 bit Big Endian using low three bytes in 32-bit word + SoundIoFormatS32LE, ///< Signed 32 bit Little Endian + SoundIoFormatS32BE, ///< Signed 32 bit Big Endian + SoundIoFormatU32LE, ///< Unsigned 32 bit Little Endian + SoundIoFormatU32BE, ///< Unsigned 32 bit Big Endian + SoundIoFormatFloat32LE, ///< Float 32 bit Little Endian, Range -1.0 to 1.0 + SoundIoFormatFloat32BE, ///< Float 32 bit Big Endian, Range -1.0 to 1.0 + SoundIoFormatFloat64LE, ///< Float 64 bit Little Endian, Range -1.0 to 1.0 + SoundIoFormatFloat64BE, ///< Float 64 bit Big Endian, Range -1.0 to 1.0 +}; + +#if defined(SOUNDIO_OS_BIG_ENDIAN) +#define SoundIoFormatS16NE SoundIoFormatS16BE +#define SoundIoFormatU16NE SoundIoFormatU16BE +#define SoundIoFormatS24NE SoundIoFormatS24BE +#define SoundIoFormatU24NE SoundIoFormatU24BE +#define SoundIoFormatS32NE SoundIoFormatS32BE +#define SoundIoFormatU32NE SoundIoFormatU32BE +#define SoundIoFormatFloat32NE SoundIoFormatFloat32BE +#define SoundIoFormatFloat64NE SoundIoFormatFloat64BE + +#define SoundIoFormatS16FE SoundIoFormatS16LE +#define SoundIoFormatU16FE SoundIoFormatU16LE +#define SoundIoFormatS24FE SoundIoFormatS24LE +#define SoundIoFormatU24FE SoundIoFormatU24LE +#define SoundIoFormatS32FE SoundIoFormatS32LE +#define SoundIoFormatU32FE SoundIoFormatU32LE +#define SoundIoFormatFloat32FE SoundIoFormatFloat32LE +#define SoundIoFormatFloat64FE SoundIoFormatFloat64LE + +#elif defined(SOUNDIO_OS_LITTLE_ENDIAN) + +/// Note that we build the documentation in Little Endian mode, +/// so all the "NE" macros in the docs point to "LE" and +/// "FE" macros point to "BE". On a Big Endian system it is the +/// other way around. +#define SoundIoFormatS16NE SoundIoFormatS16LE +#define SoundIoFormatU16NE SoundIoFormatU16LE +#define SoundIoFormatS24NE SoundIoFormatS24LE +#define SoundIoFormatU24NE SoundIoFormatU24LE +#define SoundIoFormatS32NE SoundIoFormatS32LE +#define SoundIoFormatU32NE SoundIoFormatU32LE +#define SoundIoFormatFloat32NE SoundIoFormatFloat32LE +#define SoundIoFormatFloat64NE SoundIoFormatFloat64LE + +#define SoundIoFormatS16FE SoundIoFormatS16BE +#define SoundIoFormatU16FE SoundIoFormatU16BE +#define SoundIoFormatS24FE SoundIoFormatS24BE +#define SoundIoFormatU24FE SoundIoFormatU24BE +#define SoundIoFormatS32FE SoundIoFormatS32BE +#define SoundIoFormatU32FE SoundIoFormatU32BE +#define SoundIoFormatFloat32FE SoundIoFormatFloat32BE +#define SoundIoFormatFloat64FE SoundIoFormatFloat64BE + +#else +#error unknown byte order +#endif + +#define SOUNDIO_MAX_CHANNELS 24 +/// The size of this struct is OK to use. +struct SoundIoChannelLayout { + const char *name; + int channel_count; + enum SoundIoChannelId channels[SOUNDIO_MAX_CHANNELS]; +}; + +/// The size of this struct is OK to use. +struct SoundIoSampleRateRange { + int min; + int max; +}; + +/// The size of this struct is OK to use. +struct SoundIoChannelArea { + /// Base address of buffer. + char *ptr; + /// How many bytes it takes to get from the beginning of one sample to + /// the beginning of the next sample. + int step; +}; + +/// The size of this struct is not part of the API or ABI. +struct SoundIo { + /// Optional. Put whatever you want here. Defaults to NULL. + void *userdata; + /// Optional callback. Called when the list of devices change. Only called + /// during a call to ::soundio_flush_events or ::soundio_wait_events. + void (*on_devices_change)(struct SoundIo *); + /// Optional callback. Called when the backend disconnects. For example, + /// when the JACK server shuts down. When this happens, listing devices + /// and opening streams will always fail with + /// SoundIoErrorBackendDisconnected. This callback is only called during a + /// call to ::soundio_flush_events or ::soundio_wait_events. + /// If you do not supply a callback, the default will crash your program + /// with an error message. This callback is also called when the thread + /// that retrieves device information runs into an unrecoverable condition + /// such as running out of memory. + /// + /// Possible errors: + /// * #SoundIoErrorBackendDisconnected + /// * #SoundIoErrorNoMem + /// * #SoundIoErrorSystemResources + /// * #SoundIoErrorOpeningDevice - unexpected problem accessing device + /// information + void (*on_backend_disconnect)(struct SoundIo *, int err); + /// Optional callback. Called from an unknown thread that you should not use + /// to call any soundio functions. You may use this to signal a condition + /// variable to wake up. Called when ::soundio_wait_events would be woken up. + void (*on_events_signal)(struct SoundIo *); + + /// Read-only. After calling ::soundio_connect or ::soundio_connect_backend, + /// this field tells which backend is currently connected. + enum SoundIoBackend current_backend; + + /// Optional: Application name. + /// PulseAudio uses this for "application name". + /// JACK uses this for `client_name`. + /// Must not contain a colon (":"). + const char *app_name; + + /// Optional: Real time priority warning. + /// This callback is fired when making thread real-time priority failed. By + /// default, it will print to stderr only the first time it is called + /// a message instructing the user how to configure their system to allow + /// real-time priority threads. This must be set to a function not NULL. + /// To silence the warning, assign this to a function that does nothing. + void (*emit_rtprio_warning)(void); + + /// Optional: JACK info callback. + /// By default, libsoundio sets this to an empty function in order to + /// silence stdio messages from JACK. You may override the behavior by + /// setting this to `NULL` or providing your own function. This is + /// registered with JACK regardless of whether ::soundio_connect_backend + /// succeeds. + void (*jack_info_callback)(const char *msg); + /// Optional: JACK error callback. + /// See SoundIo::jack_info_callback + void (*jack_error_callback)(const char *msg); +}; + +/// The size of this struct is not part of the API or ABI. +struct SoundIoDevice { + /// Read-only. Set automatically. + struct SoundIo *soundio; + + /// A string of bytes that uniquely identifies this device. + /// If the same physical device supports both input and output, that makes + /// one SoundIoDevice for the input and one SoundIoDevice for the output. + /// In this case, the id of each SoundIoDevice will be the same, and + /// SoundIoDevice::aim will be different. Additionally, if the device + /// supports raw mode, there may be up to four devices with the same id: + /// one for each value of SoundIoDevice::is_raw and one for each value of + /// SoundIoDevice::aim. + char *id; + /// User-friendly UTF-8 encoded text to describe the device. + char *name; + + /// Tells whether this device is an input device or an output device. + enum SoundIoDeviceAim aim; + + /// Channel layouts are handled similarly to SoundIoDevice::formats. + /// If this information is missing due to a SoundIoDevice::probe_error, + /// layouts will be NULL. It's OK to modify this data, for example calling + /// ::soundio_sort_channel_layouts on it. + /// Devices are guaranteed to have at least 1 channel layout. + struct SoundIoChannelLayout *layouts; + int layout_count; + /// See SoundIoDevice::current_format + struct SoundIoChannelLayout current_layout; + + /// List of formats this device supports. See also + /// SoundIoDevice::current_format. + enum SoundIoFormat *formats; + /// How many formats are available in SoundIoDevice::formats. + int format_count; + /// A device is either a raw device or it is a virtual device that is + /// provided by a software mixing service such as dmix or PulseAudio (see + /// SoundIoDevice::is_raw). If it is a raw device, + /// current_format is meaningless; + /// the device has no current format until you open it. On the other hand, + /// if it is a virtual device, current_format describes the + /// destination sample format that your audio will be converted to. Or, + /// if you're the lucky first application to open the device, you might + /// cause the current_format to change to your format. + /// Generally, you want to ignore current_format and use + /// whatever format is most convenient + /// for you which is supported by the device, because when you are the only + /// application left, the mixer might decide to switch + /// current_format to yours. You can learn the supported formats via + /// formats and SoundIoDevice::format_count. If this information is missing + /// due to a probe error, formats will be `NULL`. If current_format is + /// unavailable, it will be set to #SoundIoFormatInvalid. + /// Devices are guaranteed to have at least 1 format available. + enum SoundIoFormat current_format; + + /// Sample rate is the number of frames per second. + /// Sample rate is handled very similar to SoundIoDevice::formats. + /// If sample rate information is missing due to a probe error, the field + /// will be set to NULL. + /// Devices which have SoundIoDevice::probe_error set to #SoundIoErrorNone are + /// guaranteed to have at least 1 sample rate available. + struct SoundIoSampleRateRange *sample_rates; + /// How many sample rate ranges are available in + /// SoundIoDevice::sample_rates. 0 if sample rate information is missing + /// due to a probe error. + int sample_rate_count; + /// See SoundIoDevice::current_format + /// 0 if sample rate information is missing due to a probe error. + int sample_rate_current; + + /// Software latency minimum in seconds. If this value is unknown or + /// irrelevant, it is set to 0.0. + /// For PulseAudio and WASAPI this value is unknown until you open a + /// stream. + double software_latency_min; + /// Software latency maximum in seconds. If this value is unknown or + /// irrelevant, it is set to 0.0. + /// For PulseAudio and WASAPI this value is unknown until you open a + /// stream. + double software_latency_max; + /// Software latency in seconds. If this value is unknown or + /// irrelevant, it is set to 0.0. + /// For PulseAudio and WASAPI this value is unknown until you open a + /// stream. + /// See SoundIoDevice::current_format + double software_latency_current; + + /// Raw means that you are directly opening the hardware device and not + /// going through a proxy such as dmix, PulseAudio, or JACK. When you open a + /// raw device, other applications on the computer are not able to + /// simultaneously access the device. Raw devices do not perform automatic + /// resampling and thus tend to have fewer formats available. + bool is_raw; + + /// Devices are reference counted. See ::soundio_device_ref and + /// ::soundio_device_unref. + int ref_count; + + /// This is set to a SoundIoError representing the result of the device + /// probe. Ideally this will be SoundIoErrorNone in which case all the + /// fields of the device will be populated. If there is an error code here + /// then information about formats, sample rates, and channel layouts might + /// be missing. + /// + /// Possible errors: + /// * #SoundIoErrorOpeningDevice + /// * #SoundIoErrorNoMem + int probe_error; +}; + +/// The size of this struct is not part of the API or ABI. +struct SoundIoOutStream { + /// Populated automatically when you call ::soundio_outstream_create. + struct SoundIoDevice *device; + + /// Defaults to #SoundIoFormatFloat32NE, followed by the first one + /// supported. + enum SoundIoFormat format; + + /// Sample rate is the number of frames per second. + /// Defaults to 48000 (and then clamped into range). + int sample_rate; + + /// Defaults to Stereo, if available, followed by the first layout + /// supported. + struct SoundIoChannelLayout layout; + + /// Ignoring hardware latency, this is the number of seconds it takes for + /// the last sample in a full buffer to be played. + /// After you call ::soundio_outstream_open, this value is replaced with the + /// actual software latency, as near to this value as possible. + /// On systems that support clearing the buffer, this defaults to a large + /// latency, potentially upwards of 2 seconds, with the understanding that + /// you will call ::soundio_outstream_clear_buffer when you want to reduce + /// the latency to 0. On systems that do not support clearing the buffer, + /// this defaults to a reasonable lower latency value. + /// + /// On backends with high latencies (such as 2 seconds), `frame_count_min` + /// will be 0, meaning you don't have to fill the entire buffer. In this + /// case, the large buffer is there if you want it; you only have to fill + /// as much as you want. On backends like JACK, `frame_count_min` will be + /// equal to `frame_count_max` and if you don't fill that many frames, you + /// will get glitches. + /// + /// If the device has unknown software latency min and max values, you may + /// still set this, but you might not get the value you requested. + /// For PulseAudio, if you set this value to non-default, it sets + /// `PA_STREAM_ADJUST_LATENCY` and is the value used for `maxlength` and + /// `tlength`. + /// + /// For JACK, this value is always equal to + /// SoundIoDevice::software_latency_current of the device. + double software_latency; + /// Core Audio and WASAPI only: current output Audio Unit volume. Float, 0.0-1.0. + float volume; + /// Defaults to NULL. Put whatever you want here. + void *userdata; + /// In this callback, you call ::soundio_outstream_begin_write and + /// ::soundio_outstream_end_write as many times as necessary to write + /// at minimum `frame_count_min` frames and at maximum `frame_count_max` + /// frames. `frame_count_max` will always be greater than 0. Note that you + /// should write as many frames as you can; `frame_count_min` might be 0 and + /// you can still get a buffer underflow if you always write + /// `frame_count_min` frames. + /// + /// For Dummy, ALSA, and PulseAudio, `frame_count_min` will be 0. For JACK + /// and CoreAudio `frame_count_min` will be equal to `frame_count_max`. + /// + /// The code in the supplied function must be suitable for real-time + /// execution. That means that it cannot call functions that might block + /// for a long time. This includes all I/O functions (disk, TTY, network), + /// malloc, free, printf, pthread_mutex_lock, sleep, wait, poll, select, + /// pthread_join, pthread_cond_wait, etc. + void (*write_callback)(struct SoundIoOutStream *, + int frame_count_min, int frame_count_max); + /// This optional callback happens when the sound device runs out of + /// buffered audio data to play. After this occurs, the outstream waits + /// until the buffer is full to resume playback. + /// This is called from the SoundIoOutStream::write_callback thread context. + void (*underflow_callback)(struct SoundIoOutStream *); + /// Optional callback. `err` is always SoundIoErrorStreaming. + /// SoundIoErrorStreaming is an unrecoverable error. The stream is in an + /// invalid state and must be destroyed. + /// If you do not supply error_callback, the default callback will print + /// a message to stderr and then call `abort`. + /// This is called from the SoundIoOutStream::write_callback thread context. + void (*error_callback)(struct SoundIoOutStream *, int err); + + /// Optional: Name of the stream. Defaults to "SoundIoOutStream" + /// PulseAudio uses this for the stream name. + /// JACK uses this for the client name of the client that connects when you + /// open the stream. + /// WASAPI uses this for the session display name. + /// Must not contain a colon (":"). + const char *name; + + /// Optional: Hint that this output stream is nonterminal. This is used by + /// JACK and it means that the output stream data originates from an input + /// stream. Defaults to `false`. + bool non_terminal_hint; + + + /// computed automatically when you call ::soundio_outstream_open + int bytes_per_frame; + /// computed automatically when you call ::soundio_outstream_open + int bytes_per_sample; + + /// If setting the channel layout fails for some reason, this field is set + /// to an error code. Possible error codes are: + /// * #SoundIoErrorIncompatibleDevice + int layout_error; +}; + +/// The size of this struct is not part of the API or ABI. +struct SoundIoInStream { + /// Populated automatically when you call ::soundio_outstream_create. + struct SoundIoDevice *device; + + /// Defaults to #SoundIoFormatFloat32NE, followed by the first one + /// supported. + enum SoundIoFormat format; + + /// Sample rate is the number of frames per second. + /// Defaults to max(sample_rate_min, min(sample_rate_max, 48000)) + int sample_rate; + + /// Defaults to Stereo, if available, followed by the first layout + /// supported. + struct SoundIoChannelLayout layout; + + /// Ignoring hardware latency, this is the number of seconds it takes for a + /// captured sample to become available for reading. + /// After you call ::soundio_instream_open, this value is replaced with the + /// actual software latency, as near to this value as possible. + /// A higher value means less CPU usage. Defaults to a large value, + /// potentially upwards of 2 seconds. + /// If the device has unknown software latency min and max values, you may + /// still set this, but you might not get the value you requested. + /// For PulseAudio, if you set this value to non-default, it sets + /// `PA_STREAM_ADJUST_LATENCY` and is the value used for `fragsize`. + /// For JACK, this value is always equal to + /// SoundIoDevice::software_latency_current + double software_latency; + + /// Defaults to NULL. Put whatever you want here. + void *userdata; + + + /// In this function call ::soundio_instream_begin_read and + /// ::soundio_instream_end_read as many times as necessary to read at + /// minimum `frame_count_min` frames and at maximum `frame_count_max` + /// frames. If you return from read_callback without having read + /// `frame_count_min`, the frames will be dropped. `frame_count_max` is how + /// many frames are available to read. + /// + /// The code in the supplied function must be suitable for real-time + /// execution. That means that it cannot call functions that might block + /// for a long time. This includes all I/O functions (disk, TTY, network), + /// malloc, free, printf, pthread_mutex_lock, sleep, wait, poll, select, + /// pthread_join, pthread_cond_wait, etc. + void (*read_callback)(struct SoundIoInStream *, int frame_count_min, int frame_count_max); + /// This optional callback happens when the sound device buffer is full, + /// yet there is more captured audio to put in it. + /// This is never fired for PulseAudio. + /// This is called from the SoundIoInStream::read_callback thread context. + void (*overflow_callback)(struct SoundIoInStream *); + /// Optional callback. `err` is always SoundIoErrorStreaming. + /// SoundIoErrorStreaming is an unrecoverable error. The stream is in an + /// invalid state and must be destroyed. + /// If you do not supply `error_callback`, the default callback will print + /// a message to stderr and then abort(). + /// This is called from the SoundIoInStream::read_callback thread context. + void (*error_callback)(struct SoundIoInStream *, int err); + + /// Optional: Name of the stream. Defaults to "SoundIoInStream"; + /// PulseAudio uses this for the stream name. + /// JACK uses this for the client name of the client that connects when you + /// open the stream. + /// WASAPI uses this for the session display name. + /// Must not contain a colon (":"). + const char *name; + + /// Optional: Hint that this input stream is nonterminal. This is used by + /// JACK and it means that the data received by the stream will be + /// passed on or made available to another stream. Defaults to `false`. + bool non_terminal_hint; + + /// computed automatically when you call ::soundio_instream_open + int bytes_per_frame; + /// computed automatically when you call ::soundio_instream_open + int bytes_per_sample; + + /// If setting the channel layout fails for some reason, this field is set + /// to an error code. Possible error codes are: #SoundIoErrorIncompatibleDevice + int layout_error; +}; + +/// See also ::soundio_version_major, ::soundio_version_minor, ::soundio_version_patch +SOUNDIO_EXPORT const char *soundio_version_string(void); +/// See also ::soundio_version_string, ::soundio_version_minor, ::soundio_version_patch +SOUNDIO_EXPORT int soundio_version_major(void); +/// See also ::soundio_version_major, ::soundio_version_string, ::soundio_version_patch +SOUNDIO_EXPORT int soundio_version_minor(void); +/// See also ::soundio_version_major, ::soundio_version_minor, ::soundio_version_string +SOUNDIO_EXPORT int soundio_version_patch(void); + +/// Create a SoundIo context. You may create multiple instances of this to +/// connect to multiple backends. Sets all fields to defaults. +/// Returns `NULL` if and only if memory could not be allocated. +/// See also ::soundio_destroy +SOUNDIO_EXPORT struct SoundIo *soundio_create(void); +SOUNDIO_EXPORT void soundio_destroy(struct SoundIo *soundio); + + +/// Tries ::soundio_connect_backend on all available backends in order. +/// Possible errors: +/// * #SoundIoErrorInvalid - already connected +/// * #SoundIoErrorNoMem +/// * #SoundIoErrorSystemResources +/// * #SoundIoErrorNoSuchClient - when JACK returns `JackNoSuchClient` +/// See also ::soundio_disconnect +SOUNDIO_EXPORT int soundio_connect(struct SoundIo *soundio); +/// Instead of calling ::soundio_connect you may call this function to try a +/// specific backend. +/// Possible errors: +/// * #SoundIoErrorInvalid - already connected or invalid backend parameter +/// * #SoundIoErrorNoMem +/// * #SoundIoErrorBackendUnavailable - backend was not compiled in +/// * #SoundIoErrorSystemResources +/// * #SoundIoErrorNoSuchClient - when JACK returns `JackNoSuchClient` +/// * #SoundIoErrorInitAudioBackend - requested `backend` is not active +/// * #SoundIoErrorBackendDisconnected - backend disconnected while connecting +/// See also ::soundio_disconnect +SOUNDIO_EXPORT int soundio_connect_backend(struct SoundIo *soundio, enum SoundIoBackend backend); +SOUNDIO_EXPORT void soundio_disconnect(struct SoundIo *soundio); + +/// Get a string representation of a #SoundIoError +SOUNDIO_EXPORT const char *soundio_strerror(int error); +/// Get a string representation of a #SoundIoBackend +SOUNDIO_EXPORT const char *soundio_backend_name(enum SoundIoBackend backend); + +/// Returns the number of available backends. +SOUNDIO_EXPORT int soundio_backend_count(struct SoundIo *soundio); +/// get the available backend at the specified index +/// (0 <= index < ::soundio_backend_count) +SOUNDIO_EXPORT enum SoundIoBackend soundio_get_backend(struct SoundIo *soundio, int index); + +/// Returns whether libsoundio was compiled with backend. +SOUNDIO_EXPORT bool soundio_have_backend(enum SoundIoBackend backend); + +/// Atomically update information for all connected devices. Note that calling +/// this function merely flips a pointer; the actual work of collecting device +/// information is done elsewhere. It is performant to call this function many +/// times per second. +/// +/// When you call this, the following callbacks might be called: +/// * SoundIo::on_devices_change +/// * SoundIo::on_backend_disconnect +/// This is the only time those callbacks can be called. +/// +/// This must be called from the same thread as the thread in which you call +/// these functions: +/// * ::soundio_input_device_count +/// * ::soundio_output_device_count +/// * ::soundio_get_input_device +/// * ::soundio_get_output_device +/// * ::soundio_default_input_device_index +/// * ::soundio_default_output_device_index +/// +/// Note that if you do not care about learning about updated devices, you +/// might call this function only once ever and never call +/// ::soundio_wait_events. +SOUNDIO_EXPORT void soundio_flush_events(struct SoundIo *soundio); + +/// This function calls ::soundio_flush_events then blocks until another event +/// is ready or you call ::soundio_wakeup. Be ready for spurious wakeups. +SOUNDIO_EXPORT void soundio_wait_events(struct SoundIo *soundio); + +/// Makes ::soundio_wait_events stop blocking. +SOUNDIO_EXPORT void soundio_wakeup(struct SoundIo *soundio); + + +/// If necessary you can manually trigger a device rescan. Normally you will +/// not ever have to call this function, as libsoundio listens to system events +/// for device changes and responds to them by rescanning devices and preparing +/// the new device information for you to be atomically replaced when you call +/// ::soundio_flush_events. However you might run into cases where you want to +/// force trigger a device rescan, for example if an ALSA device has a +/// SoundIoDevice::probe_error. +/// +/// After you call this you still have to use ::soundio_flush_events or +/// ::soundio_wait_events and then wait for the +/// SoundIo::on_devices_change callback. +/// +/// This can be called from any thread context except for +/// SoundIoOutStream::write_callback and SoundIoInStream::read_callback +SOUNDIO_EXPORT void soundio_force_device_scan(struct SoundIo *soundio); + + +// Channel Layouts + +/// Returns whether the channel count field and each channel id matches in +/// the supplied channel layouts. +SOUNDIO_EXPORT bool soundio_channel_layout_equal( + const struct SoundIoChannelLayout *a, + const struct SoundIoChannelLayout *b); + +SOUNDIO_EXPORT const char *soundio_get_channel_name(enum SoundIoChannelId id); +/// Given UTF-8 encoded text which is the name of a channel such as +/// "Front Left", "FL", or "front-left", return the corresponding +/// SoundIoChannelId. Returns SoundIoChannelIdInvalid for no match. +SOUNDIO_EXPORT enum SoundIoChannelId soundio_parse_channel_id(const char *str, int str_len); + +/// Returns the number of builtin channel layouts. +SOUNDIO_EXPORT int soundio_channel_layout_builtin_count(void); +/// Returns a builtin channel layout. 0 <= `index` < ::soundio_channel_layout_builtin_count +/// +/// Although `index` is of type `int`, it should be a valid +/// #SoundIoChannelLayoutId enum value. +SOUNDIO_EXPORT const struct SoundIoChannelLayout *soundio_channel_layout_get_builtin(int index); + +/// Get the default builtin channel layout for the given number of channels. +SOUNDIO_EXPORT const struct SoundIoChannelLayout *soundio_channel_layout_get_default(int channel_count); + +/// Return the index of `channel` in `layout`, or `-1` if not found. +SOUNDIO_EXPORT int soundio_channel_layout_find_channel( + const struct SoundIoChannelLayout *layout, enum SoundIoChannelId channel); + +/// Populates the name field of layout if it matches a builtin one. +/// returns whether it found a match +SOUNDIO_EXPORT bool soundio_channel_layout_detect_builtin(struct SoundIoChannelLayout *layout); + +/// Iterates over preferred_layouts. Returns the first channel layout in +/// preferred_layouts which matches one of the channel layouts in +/// available_layouts. Returns NULL if none matches. +SOUNDIO_EXPORT const struct SoundIoChannelLayout *soundio_best_matching_channel_layout( + const struct SoundIoChannelLayout *preferred_layouts, int preferred_layout_count, + const struct SoundIoChannelLayout *available_layouts, int available_layout_count); + +/// Sorts by channel count, descending. +SOUNDIO_EXPORT void soundio_sort_channel_layouts(struct SoundIoChannelLayout *layouts, int layout_count); + + +// Sample Formats + +/// Returns -1 on invalid format. +SOUNDIO_EXPORT int soundio_get_bytes_per_sample(enum SoundIoFormat format); + +/// A frame is one sample per channel. +static inline int soundio_get_bytes_per_frame(enum SoundIoFormat format, int channel_count) { + return soundio_get_bytes_per_sample(format) * channel_count; +} + +/// Sample rate is the number of frames per second. +static inline int soundio_get_bytes_per_second(enum SoundIoFormat format, + int channel_count, int sample_rate) +{ + return soundio_get_bytes_per_frame(format, channel_count) * sample_rate; +} + +/// Returns string representation of `format`. +SOUNDIO_EXPORT const char * soundio_format_string(enum SoundIoFormat format); + + + + +// Devices + +/// When you call ::soundio_flush_events, a snapshot of all device state is +/// saved and these functions merely access the snapshot data. When you want +/// to check for new devices, call ::soundio_flush_events. Or you can call +/// ::soundio_wait_events to block until devices change. If an error occurs +/// scanning devices in a background thread, SoundIo::on_backend_disconnect is called +/// with the error code. + +/// Get the number of input devices. +/// Returns -1 if you never called ::soundio_flush_events. +SOUNDIO_EXPORT int soundio_input_device_count(struct SoundIo *soundio); +/// Get the number of output devices. +/// Returns -1 if you never called ::soundio_flush_events. +SOUNDIO_EXPORT int soundio_output_device_count(struct SoundIo *soundio); + +/// Always returns a device. Call ::soundio_device_unref when done. +/// `index` must be 0 <= index < ::soundio_input_device_count +/// Returns NULL if you never called ::soundio_flush_events or if you provide +/// invalid parameter values. +SOUNDIO_EXPORT struct SoundIoDevice *soundio_get_input_device(struct SoundIo *soundio, int index); +/// Always returns a device. Call ::soundio_device_unref when done. +/// `index` must be 0 <= index < ::soundio_output_device_count +/// Returns NULL if you never called ::soundio_flush_events or if you provide +/// invalid parameter values. +SOUNDIO_EXPORT struct SoundIoDevice *soundio_get_output_device(struct SoundIo *soundio, int index); + +/// returns the index of the default input device +/// returns -1 if there are no devices or if you never called +/// ::soundio_flush_events. +SOUNDIO_EXPORT int soundio_default_input_device_index(struct SoundIo *soundio); + +/// returns the index of the default output device +/// returns -1 if there are no devices or if you never called +/// ::soundio_flush_events. +SOUNDIO_EXPORT int soundio_default_output_device_index(struct SoundIo *soundio); + +/// Add 1 to the reference count of `device`. +SOUNDIO_EXPORT void soundio_device_ref(struct SoundIoDevice *device); +/// Remove 1 to the reference count of `device`. Clean up if it was the last +/// reference. +SOUNDIO_EXPORT void soundio_device_unref(struct SoundIoDevice *device); + +/// Return `true` if and only if the devices have the same SoundIoDevice::id, +/// SoundIoDevice::is_raw, and SoundIoDevice::aim are the same. +SOUNDIO_EXPORT bool soundio_device_equal( + const struct SoundIoDevice *a, + const struct SoundIoDevice *b); + +/// Sorts channel layouts by channel count, descending. +SOUNDIO_EXPORT void soundio_device_sort_channel_layouts(struct SoundIoDevice *device); + +/// Convenience function. Returns whether `format` is included in the device's +/// supported formats. +SOUNDIO_EXPORT bool soundio_device_supports_format(struct SoundIoDevice *device, + enum SoundIoFormat format); + +/// Convenience function. Returns whether `layout` is included in the device's +/// supported channel layouts. +SOUNDIO_EXPORT bool soundio_device_supports_layout(struct SoundIoDevice *device, + const struct SoundIoChannelLayout *layout); + +/// Convenience function. Returns whether `sample_rate` is included in the +/// device's supported sample rates. +SOUNDIO_EXPORT bool soundio_device_supports_sample_rate(struct SoundIoDevice *device, + int sample_rate); + +/// Convenience function. Returns the available sample rate nearest to +/// `sample_rate`, rounding up. +SOUNDIO_EXPORT int soundio_device_nearest_sample_rate(struct SoundIoDevice *device, + int sample_rate); + + + +// Output Streams +/// Allocates memory and sets defaults. Next you should fill out the struct fields +/// and then call ::soundio_outstream_open. Sets all fields to defaults. +/// Returns `NULL` if and only if memory could not be allocated. +/// See also ::soundio_outstream_destroy +SOUNDIO_EXPORT struct SoundIoOutStream *soundio_outstream_create(struct SoundIoDevice *device); +/// You may not call this function from the SoundIoOutStream::write_callback thread context. +SOUNDIO_EXPORT void soundio_outstream_destroy(struct SoundIoOutStream *outstream); + +/// After you call this function, SoundIoOutStream::software_latency is set to +/// the correct value. +/// +/// The next thing to do is call ::soundio_outstream_start. +/// If this function returns an error, the outstream is in an invalid state and +/// you must call ::soundio_outstream_destroy on it. +/// +/// Possible errors: +/// * #SoundIoErrorInvalid +/// * SoundIoDevice::aim is not #SoundIoDeviceAimOutput +/// * SoundIoOutStream::format is not valid +/// * SoundIoOutStream::channel_count is greater than #SOUNDIO_MAX_CHANNELS +/// * #SoundIoErrorNoMem +/// * #SoundIoErrorOpeningDevice +/// * #SoundIoErrorBackendDisconnected +/// * #SoundIoErrorSystemResources +/// * #SoundIoErrorNoSuchClient - when JACK returns `JackNoSuchClient` +/// * #SoundIoErrorIncompatibleBackend - SoundIoOutStream::channel_count is +/// greater than the number of channels the backend can handle. +/// * #SoundIoErrorIncompatibleDevice - stream parameters requested are not +/// compatible with the chosen device. +SOUNDIO_EXPORT int soundio_outstream_open(struct SoundIoOutStream *outstream); + +/// After you call this function, SoundIoOutStream::write_callback will be called. +/// +/// This function might directly call SoundIoOutStream::write_callback. +/// +/// Possible errors: +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorNoMem +/// * #SoundIoErrorSystemResources +/// * #SoundIoErrorBackendDisconnected +SOUNDIO_EXPORT int soundio_outstream_start(struct SoundIoOutStream *outstream); + +/// Call this function when you are ready to begin writing to the device buffer. +/// * `outstream` - (in) The output stream you want to write to. +/// * `areas` - (out) The memory addresses you can write data to, one per +/// channel. It is OK to modify the pointers if that helps you iterate. +/// * `frame_count` - (in/out) Provide the number of frames you want to write. +/// Returned will be the number of frames you can actually write, which is +/// also the number of frames that will be written when you call +/// ::soundio_outstream_end_write. The value returned will always be less +/// than or equal to the value provided. +/// It is your responsibility to call this function exactly as many times as +/// necessary to meet the `frame_count_min` and `frame_count_max` criteria from +/// SoundIoOutStream::write_callback. +/// You must call this function only from the SoundIoOutStream::write_callback thread context. +/// After calling this function, write data to `areas` and then call +/// ::soundio_outstream_end_write. +/// If this function returns an error, do not call ::soundio_outstream_end_write. +/// +/// Possible errors: +/// * #SoundIoErrorInvalid +/// * `*frame_count` <= 0 +/// * `*frame_count` < `frame_count_min` or `*frame_count` > `frame_count_max` +/// * function called too many times without respecting `frame_count_max` +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorUnderflow - an underflow caused this call to fail. You might +/// also get a SoundIoOutStream::underflow_callback, and you might not get +/// this error code when an underflow occurs. Unlike #SoundIoErrorStreaming, +/// the outstream is still in a valid state and streaming can continue. +/// * #SoundIoErrorIncompatibleDevice - in rare cases it might just now +/// be discovered that the device uses non-byte-aligned access, in which +/// case this error code is returned. +SOUNDIO_EXPORT int soundio_outstream_begin_write(struct SoundIoOutStream *outstream, + struct SoundIoChannelArea **areas, int *frame_count); + +/// Commits the write that you began with ::soundio_outstream_begin_write. +/// You must call this function only from the SoundIoOutStream::write_callback thread context. +/// +/// Possible errors: +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorUnderflow - an underflow caused this call to fail. You might +/// also get a SoundIoOutStream::underflow_callback, and you might not get +/// this error code when an underflow occurs. Unlike #SoundIoErrorStreaming, +/// the outstream is still in a valid state and streaming can continue. +SOUNDIO_EXPORT int soundio_outstream_end_write(struct SoundIoOutStream *outstream); + +/// Clears the output stream buffer. +/// This function can be called from any thread. +/// This function can be called regardless of whether the outstream is paused +/// or not. +/// Some backends do not support clearing the buffer. On these backends this +/// function will return SoundIoErrorIncompatibleBackend. +/// Some devices do not support clearing the buffer. On these devices this +/// function might return SoundIoErrorIncompatibleDevice. +/// Possible errors: +/// +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorIncompatibleBackend +/// * #SoundIoErrorIncompatibleDevice +SOUNDIO_EXPORT int soundio_outstream_clear_buffer(struct SoundIoOutStream *outstream); + +/// If the underlying backend and device support pausing, this pauses the +/// stream. SoundIoOutStream::write_callback may be called a few more times if +/// the buffer is not full. +/// Pausing might put the hardware into a low power state which is ideal if your +/// software is silent for some time. +/// This function may be called from any thread context, including +/// SoundIoOutStream::write_callback. +/// Pausing when already paused or unpausing when already unpaused has no +/// effect and returns #SoundIoErrorNone. +/// +/// Possible errors: +/// * #SoundIoErrorBackendDisconnected +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorIncompatibleDevice - device does not support +/// pausing/unpausing. This error code might not be returned even if the +/// device does not support pausing/unpausing. +/// * #SoundIoErrorIncompatibleBackend - backend does not support +/// pausing/unpausing. +/// * #SoundIoErrorInvalid - outstream not opened and started +SOUNDIO_EXPORT int soundio_outstream_pause(struct SoundIoOutStream *outstream, bool pause); + +/// Obtain the total number of seconds that the next frame written after the +/// last frame written with ::soundio_outstream_end_write will take to become +/// audible. This includes both software and hardware latency. In other words, +/// if you call this function directly after calling ::soundio_outstream_end_write, +/// this gives you the number of seconds that the next frame written will take +/// to become audible. +/// +/// This function must be called only from within SoundIoOutStream::write_callback. +/// +/// Possible errors: +/// * #SoundIoErrorStreaming +SOUNDIO_EXPORT int soundio_outstream_get_latency(struct SoundIoOutStream *outstream, + double *out_latency); + +SOUNDIO_EXPORT int soundio_outstream_set_volume(struct SoundIoOutStream *outstream, + double volume); + + + +// Input Streams +/// Allocates memory and sets defaults. Next you should fill out the struct fields +/// and then call ::soundio_instream_open. Sets all fields to defaults. +/// Returns `NULL` if and only if memory could not be allocated. +/// See also ::soundio_instream_destroy +SOUNDIO_EXPORT struct SoundIoInStream *soundio_instream_create(struct SoundIoDevice *device); +/// You may not call this function from SoundIoInStream::read_callback. +SOUNDIO_EXPORT void soundio_instream_destroy(struct SoundIoInStream *instream); + +/// After you call this function, SoundIoInStream::software_latency is set to the correct +/// value. +/// The next thing to do is call ::soundio_instream_start. +/// If this function returns an error, the instream is in an invalid state and +/// you must call ::soundio_instream_destroy on it. +/// +/// Possible errors: +/// * #SoundIoErrorInvalid +/// * device aim is not #SoundIoDeviceAimInput +/// * format is not valid +/// * requested layout channel count > #SOUNDIO_MAX_CHANNELS +/// * #SoundIoErrorOpeningDevice +/// * #SoundIoErrorNoMem +/// * #SoundIoErrorBackendDisconnected +/// * #SoundIoErrorSystemResources +/// * #SoundIoErrorNoSuchClient +/// * #SoundIoErrorIncompatibleBackend +/// * #SoundIoErrorIncompatibleDevice +SOUNDIO_EXPORT int soundio_instream_open(struct SoundIoInStream *instream); + +/// After you call this function, SoundIoInStream::read_callback will be called. +/// +/// Possible errors: +/// * #SoundIoErrorBackendDisconnected +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorOpeningDevice +/// * #SoundIoErrorSystemResources +SOUNDIO_EXPORT int soundio_instream_start(struct SoundIoInStream *instream); + +/// Call this function when you are ready to begin reading from the device +/// buffer. +/// * `instream` - (in) The input stream you want to read from. +/// * `areas` - (out) The memory addresses you can read data from. It is OK +/// to modify the pointers if that helps you iterate. There might be a "hole" +/// in the buffer. To indicate this, `areas` will be `NULL` and `frame_count` +/// tells how big the hole is in frames. +/// * `frame_count` - (in/out) - Provide the number of frames you want to read; +/// returns the number of frames you can actually read. The returned value +/// will always be less than or equal to the provided value. If the provided +/// value is less than `frame_count_min` from SoundIoInStream::read_callback this function +/// returns with #SoundIoErrorInvalid. +/// It is your responsibility to call this function no more and no fewer than the +/// correct number of times according to the `frame_count_min` and +/// `frame_count_max` criteria from SoundIoInStream::read_callback. +/// You must call this function only from the SoundIoInStream::read_callback thread context. +/// After calling this function, read data from `areas` and then use +/// ::soundio_instream_end_read` to actually remove the data from the buffer +/// and move the read index forward. ::soundio_instream_end_read should not be +/// called if the buffer is empty (`frame_count` == 0), but it should be called +/// if there is a hole. +/// +/// Possible errors: +/// * #SoundIoErrorInvalid +/// * `*frame_count` < `frame_count_min` or `*frame_count` > `frame_count_max` +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorIncompatibleDevice - in rare cases it might just now +/// be discovered that the device uses non-byte-aligned access, in which +/// case this error code is returned. +SOUNDIO_EXPORT int soundio_instream_begin_read(struct SoundIoInStream *instream, + struct SoundIoChannelArea **areas, int *frame_count); +/// This will drop all of the frames from when you called +/// ::soundio_instream_begin_read. +/// You must call this function only from the SoundIoInStream::read_callback thread context. +/// You must call this function only after a successful call to +/// ::soundio_instream_begin_read. +/// +/// Possible errors: +/// * #SoundIoErrorStreaming +SOUNDIO_EXPORT int soundio_instream_end_read(struct SoundIoInStream *instream); + +/// If the underyling device supports pausing, this pauses the stream and +/// prevents SoundIoInStream::read_callback from being called. Otherwise this returns +/// #SoundIoErrorIncompatibleDevice. +/// This function may be called from any thread. +/// Pausing when already paused or unpausing when already unpaused has no +/// effect and always returns #SoundIoErrorNone. +/// +/// Possible errors: +/// * #SoundIoErrorBackendDisconnected +/// * #SoundIoErrorStreaming +/// * #SoundIoErrorIncompatibleDevice - device does not support pausing/unpausing +SOUNDIO_EXPORT int soundio_instream_pause(struct SoundIoInStream *instream, bool pause); + +/// Obtain the number of seconds that the next frame of sound being +/// captured will take to arrive in the buffer, plus the amount of time that is +/// represented in the buffer. This includes both software and hardware latency. +/// +/// This function must be called only from within SoundIoInStream::read_callback. +/// +/// Possible errors: +/// * #SoundIoErrorStreaming +SOUNDIO_EXPORT int soundio_instream_get_latency(struct SoundIoInStream *instream, + double *out_latency); + + +struct SoundIoRingBuffer; + +/// A ring buffer is a single-reader single-writer lock-free fixed-size queue. +/// libsoundio ring buffers use memory mapping techniques to enable a +/// contiguous buffer when reading or writing across the boundary of the ring +/// buffer's capacity. +/// `requested_capacity` in bytes. +/// Returns `NULL` if and only if memory could not be allocated. +/// Use ::soundio_ring_buffer_capacity to get the actual capacity, which might +/// be greater for alignment purposes. +/// See also ::soundio_ring_buffer_destroy +SOUNDIO_EXPORT struct SoundIoRingBuffer *soundio_ring_buffer_create(struct SoundIo *soundio, int requested_capacity); +SOUNDIO_EXPORT void soundio_ring_buffer_destroy(struct SoundIoRingBuffer *ring_buffer); + +/// When you create a ring buffer, capacity might be more than the requested +/// capacity for alignment purposes. This function returns the actual capacity. +SOUNDIO_EXPORT int soundio_ring_buffer_capacity(struct SoundIoRingBuffer *ring_buffer); + +/// Do not write more than capacity. +SOUNDIO_EXPORT char *soundio_ring_buffer_write_ptr(struct SoundIoRingBuffer *ring_buffer); +/// `count` in bytes. +SOUNDIO_EXPORT void soundio_ring_buffer_advance_write_ptr(struct SoundIoRingBuffer *ring_buffer, int count); + +/// Do not read more than capacity. +SOUNDIO_EXPORT char *soundio_ring_buffer_read_ptr(struct SoundIoRingBuffer *ring_buffer); +/// `count` in bytes. +SOUNDIO_EXPORT void soundio_ring_buffer_advance_read_ptr(struct SoundIoRingBuffer *ring_buffer, int count); + +/// Returns how many bytes of the buffer is used, ready for reading. +SOUNDIO_EXPORT int soundio_ring_buffer_fill_count(struct SoundIoRingBuffer *ring_buffer); + +/// Returns how many bytes of the buffer is free, ready for writing. +SOUNDIO_EXPORT int soundio_ring_buffer_free_count(struct SoundIoRingBuffer *ring_buffer); + +/// Must be called by the writer. +SOUNDIO_EXPORT void soundio_ring_buffer_clear(struct SoundIoRingBuffer *ring_buffer); + +#endif diff --git a/hsmodem/speed.cpp b/hsmodem/speed.cpp index 3fcb953..21cda62 100755 --- a/hsmodem/speed.cpp +++ b/hsmodem/speed.cpp @@ -160,7 +160,7 @@ void measure_speed_bps(int len) speed = meanvalbps((int)dspd); // here we have number of elements after 1s - printf("%d bit/s\n", speed); + printf(" ======================= %d bit/s\n", speed); elems = 0; lasttim = tim; diff --git a/hsmodem/voiceio.cpp b/hsmodem/voiceio.cpp new file mode 100755 index 0000000..6247062 --- /dev/null +++ b/hsmodem/voiceio.cpp @@ -0,0 +1,425 @@ +/* +* High Speed modem to transfer data in a 2,7kHz SSB channel +* ========================================================= +* Author: DJ0ABR +* +* (c) DJ0ABR +* www.dj0abr.de +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* voiceio.c ... interface to libsoundio für DV audio +* +*/ + +#include "hsmodem.h" + +struct SoundIo* voice_soundio = NULL; +struct SoundIoDevice* io_ls_device = NULL; +struct SoundIoDevice* io_mic_device = NULL; +struct SoundIoOutStream* outlsstream = NULL; +struct SoundIoInStream* inmicstream = NULL; + +void read_voicecallback(struct SoundIoInStream* instream, int frame_count_min, int frame_count_max) +{ + + int err; + //printf("cap: %d %d\n", frame_count_min, frame_count_max); + //int chans = instream->layout.channel_count; + + struct SoundIoChannelArea* areas; + // samples are in areas.ptr + int frames_left = frame_count_max; // take all + while (1) + { + int frame_count = frames_left; + if ((err = soundio_instream_begin_read(instream, &areas, &frame_count))) + { + fprintf(stderr, "begin read error: %s", soundio_strerror(err)); + exit(1); + } + if (!frame_count) + break; + + for (int frame = 0; frame < frame_count; frame += 1) + { + for (int ch = 0; ch < instream->layout.channel_count; ch += 1) + { + int16_t rxdata; + memcpy(&rxdata, areas[ch].ptr, instream->bytes_per_sample); + areas[ch].ptr += areas[ch].step; + if (ch == 0) + { + float f = rxdata; + f /= 32768; + f *= softwareCAPvolume; + io_mic_write_fifo(f); + } + } + } + + //measure_speed_bps(frame_count); + + if ((err = soundio_instream_end_read(instream))) + { + fprintf(stderr, "end read error: %s", soundio_strerror(err)); + exit(1); + } + + frames_left -= frame_count; + if (frames_left <= 0) + break; + } +} + +void overflow_voicecallback(struct SoundIoInStream* instream) +{ + static int count = 0; + printf("voice overflow %d\n", ++count); +} + +void write_sample_s16ne(char* ptr, double sample) { + int16_t* buf = (int16_t*)ptr; + double range = (double)INT16_MAX - (double)INT16_MIN; + double val = sample * range / 2.0; + *buf = (int16_t)val; +} + +#define MAXCAPCHUNKLEN 50000 + +static void write_voicecallback(struct SoundIoOutStream* outstream, int frame_count_min, int frame_count_max) +{ + struct SoundIoChannelArea* areas; + int err; + int frames_left = frame_count_max; + + while(1) + { + int frame_count = frames_left; + if ((err = soundio_outstream_begin_write(outstream, &areas, &frame_count))) + { + fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err)); + exit(1); + } + + if (!frame_count) + break; + + // soundio_outstream_begin_write requested to write frame_count elements + float f[MAXCAPCHUNKLEN]; + int fiforet = io_ls_read_fifo_num(f, frame_count); + if (fiforet == 0) + { + // elements not available, fill with zeroes + //printf("not enough data, send zeroes\n"); + memset(f, 0, sizeof(float) * frame_count); + } + + const struct SoundIoChannelLayout* layout = &outstream->layout; + + for (int frame = 0; frame < frame_count; frame++) + { + for (int channel = 0; channel < layout->channel_count; channel++) + { + write_sample_s16ne(areas[channel].ptr, f[frame]); + areas[channel].ptr += areas[channel].step; + } + } + + if ((err = soundio_outstream_end_write(outstream))) { + if (err == SoundIoErrorUnderflow) + return; + fprintf(stderr, "unrecoverable stream error: %s\n", soundio_strerror(err)); + exit(1); + } + + frames_left -= frame_count; + if (frames_left <= 0) + break; + } +} + + +/* +static void write_voicecallback(struct SoundIoOutStream* outstream, int frame_count_min, int frame_count_max) +{ + float f[MAXCAPCHUNKLEN]; + + int chans = outstream->layout.channel_count; + struct SoundIoChannelArea* areas; + int err; + int frames_left = min_int(frame_count_max, MAXCAPCHUNKLEN);// frame_count_max; + printf("min: %d max:%d\n", frame_count_min, frame_count_max); + + // we have to write frame_count_max, not less, or we get an underrun + // this has to be written in chunks requested by soundio_outstream_begin_write + + while (1) + { + int frame_count = frames_left; + if ((err = soundio_outstream_begin_write(outstream, &areas, &frame_count))) { + printf("unrecoverable soundio_outstream_begin_write error: %s\n", soundio_strerror(err)); + exit(1); + } + printf("chunk: %d\n", frame_count); + if (!frame_count) break; // will normally never happen + + // soundio_outstream_begin_write requested to write frame_count elements + int fiforet = io_ls_read_fifo_num(f, frame_count); + if (fiforet == 0) + { + // elements not available, fill with zeroes + //printf("not enough data, send zeroes\n"); + memset(f, 0, sizeof(float) * frame_count); + } + + // apply volume + for (int i = 0; i < frame_count; i++) + f[i] *= softwarePBvolume; + + // put data into soundio buffer + for (int frame = 0; frame < frame_count; frame++) + { + for (int ch = 0; ch < chans; ch++) + { + int16_t* s = (int16_t*)areas[ch].ptr; + *s = (int16_t)(f[frame] * 32768.0); + areas[ch].ptr += areas[ch].step; + } + } + + for (int frame = 0; frame < frame_count; frame += 1) + { + for (int channel = 0; channel < chans; channel += 1) + { + write_sample_float32ne(areas[channel].ptr, f[frame]); + areas[channel].ptr += areas[channel].step; + } + } + + // and finalize this chunk + if ((err = soundio_outstream_end_write(outstream))) { + if (err == SoundIoErrorUnderflow) + { + printf("underflow x\n"); + return; + } + printf("unrecoverable soundio_outstream_end_write error: %s\n", soundio_strerror(err)); + exit(1); + } + + frames_left -= frame_count; + if (frames_left <= 0) + break; + } +} +*/ + +void underflow_voicecallback(struct SoundIoOutStream* outstream) +{ + static int count = 0; + printf("voice underflow %d\n", count++); +} + + +int io_init_voice(char* lsname, char* micname) +{ + int err; + init_voice_result = 0; + + printf("\n ==== IO INIT VOICE devices ====\n"); + printf("requested: <%s> <%s>\ncapture rate:%d\n", lsname, micname, VOICE_SAMPRATE); + + io_close_voice(); + + // prepare and connect to libsoundio + voice_soundio = soundio_create(); + if (!voice_soundio) { + printf("vsoundio_create: out of memory\n"); + return 0; + } +#ifdef _WIN32_ + if ((err = soundio_connect_backend(voice_soundio, SoundIoBackendWasapi))) { + printf("vsoundio_connect: %s\n", soundio_strerror(err)); + return 0; + } +#endif +#ifdef _LINUX_ + if ((err = soundio_connect(voice_soundio))) { + printf("vsoundio_connect: %s\n", soundio_strerror(err)); + return 0; + } +#endif + + if (lsname == NULL || micname == NULL || strlen(lsname) < 3 || strlen(micname) < 3) // no devices defined yet + { + printf("no devices specified\n"); + return 0; + } + + char* lsdevid = getDevID(lsname, 1); + if (lsdevid == NULL) return 0; + + char* micdevid = getDevID(micname, 0); + if (micdevid == NULL) return 0; + + soundio_flush_events(voice_soundio); + + printf("================ %d\n", VoiceAudioMode); + if (VoiceAudioMode != VOICEMODE_LISTENAUDIOIN) + { + + // define the capture device + printf("selected CAP device:\nname:%s\nid :%s\n", micname, micdevid); + + for (int i = 0; i < soundio_input_device_count(voice_soundio); i++) + { + io_mic_device = NULL; + struct SoundIoDevice* device = soundio_get_input_device(voice_soundio, i); + if (strcmp(device->id, micdevid) == 0 +#ifdef _WIN32_ + && device->is_raw == true +#endif + ) + { + io_mic_device = device; + break; + } + soundio_device_unref(device); + } + + if (!io_mic_device) + { + printf("Invalid device id: %s\n", micdevid); + sleep_ms(2000); + return 0; + } + + if (io_mic_device->probe_error) + { + printf("Unable to probe voice device: %s\n", soundio_strerror(io_mic_device->probe_error)); + sleep_ms(2000); + return 0; + } + + printf("cap raw: %s\n", io_mic_device->is_raw ? "raw" : "---"); + + // create capture callback + inmicstream = soundio_instream_create(io_mic_device); + if (!inmicstream) { + printf("out of memory\n"); + return 0; + } + + inmicstream->format = SoundIoFormatS16NE; + inmicstream->sample_rate = VOICE_SAMPRATE; + inmicstream->software_latency = 0.0; + inmicstream->read_callback = read_voicecallback; + inmicstream->overflow_callback = overflow_voicecallback; + inmicstream->userdata = NULL; + + if ((err = soundio_instream_open(inmicstream))) { + printf("unable to open voice input stream: %s", soundio_strerror(err)); + return 0; + } + + if ((err = soundio_instream_start(inmicstream))) { + fprintf(stderr, "unable to start voice input device: %s", soundio_strerror(err)); + return 0; + } + init_voice_result |= 2; + // the CAP callback is running now + } + + // define the playback device + printf("selected PB device:\nname:%s\nid :%s\n", lsname, lsdevid); + for (int i = 0; i < soundio_output_device_count(voice_soundio); i++) + { + io_ls_device = NULL; + struct SoundIoDevice* device = soundio_get_output_device(voice_soundio, i); + if (strcmp(device->id, lsdevid) == 0 +#ifdef _WIN32_ + && device->is_raw == true +#endif + ) + { + io_ls_device = device; + break; + } + soundio_device_unref(device); + } + if (!io_ls_device) + { + printf("Invalid device id: %s\n", lsdevid); + return 0; + } + + if (io_ls_device->probe_error) + { + printf("Unable to probe device: %s\n", soundio_strerror(io_ls_device->probe_error)); + return 0; + } + + printf("pb raw: %s\n", io_ls_device->is_raw ? "raw" : "---"); + + // create playback callback + outlsstream = soundio_outstream_create(io_ls_device); + if (!outlsstream) { + printf("soundio_outstream_create: out of memory\n"); + return 0; + } + + outlsstream->format = SoundIoFormatS16NE; + outlsstream->sample_rate = VOICE_SAMPRATE; + outlsstream->software_latency = 0.0; + outlsstream->write_callback = write_voicecallback; + outlsstream->underflow_callback = underflow_voicecallback; + outlsstream->userdata = NULL; + + if ((err = soundio_outstream_open(outlsstream))) { + printf("unable to open voice output stream: %s", soundio_strerror(err)); + return 0; + } + + if ((err = soundio_outstream_start(outlsstream))) { + fprintf(stderr, "unable to start voice output device: %s", soundio_strerror(err)); + return 0; + } + init_voice_result |= 1; + + printf("==== Voice init finished: %d ====\n", init_audio_result); + + return init_voice_result; +} + +void io_close_voice() +{ + printf("close Voice\n"); + if (inmicstream) soundio_instream_destroy(inmicstream); + inmicstream = NULL; + + if (outlsstream) soundio_outstream_destroy(outlsstream); + outlsstream = NULL; + + if (io_ls_device) soundio_device_unref(io_ls_device); + io_ls_device = NULL; + + if (io_mic_device) soundio_device_unref(io_mic_device); + io_mic_device = NULL; + + if (voice_soundio) soundio_destroy(voice_soundio); + voice_soundio = NULL; + +} diff --git a/hsmodem/voiceprocessor.cpp b/hsmodem/voiceprocessor.cpp index e62cb1b..5163807 100755 --- a/hsmodem/voiceprocessor.cpp +++ b/hsmodem/voiceprocessor.cpp @@ -134,7 +134,7 @@ void encode(float f) } for (int i = 0; i < r; i++) - pb_write_fifo_voice(fresult[i]); + io_ls_write_fifo(fresult[i]); } farridx = 0; @@ -171,7 +171,7 @@ void sendCodecToModulator(uint8_t *pdata, int len) while (1) { // we have to check if the TX fifo has enough data. In case of an underrun the Q(8A)PSK signal will be distorted - int us = pb_fifo_usedspace(); + int us = io_pb_fifo_usedspace(); if (us < 20000) { //printf("tx filler\n"); @@ -245,7 +245,7 @@ void toCodecDecoder(uint8_t *pdata, int len) { //measure_speed_bps(r); for (int j = 0; j < r; j++) - pb_write_fifo_voice(fresult[j]); + io_ls_write_fifo(fresult[j]); } } } diff --git a/oscardata/oscardata/Form1.Designer.cs b/oscardata/oscardata/Form1.Designer.cs index d40c4b0..213599f 100755 --- a/oscardata/oscardata/Form1.Designer.cs +++ b/oscardata/oscardata/Form1.Designer.cs @@ -39,12 +39,12 @@ this.panel_constel = new System.Windows.Forms.Panel(); this.timer_qpsk = new System.Windows.Forms.Timer(this.components); this.panel_txspectrum = new System.Windows.Forms.Panel(); - this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage_ber = new System.Windows.Forms.TabPage(); this.button_stopBERtest = new System.Windows.Forms.Button(); this.imageList1 = new System.Windows.Forms.ImageList(this.components); this.button_startBERtest = new System.Windows.Forms.Button(); this.rtb = new System.Windows.Forms.RichTextBox(); - this.tabPage2 = new System.Windows.Forms.TabPage(); + this.tabPage_image = new System.Windows.Forms.TabPage(); this.groupBox1 = new System.Windows.Forms.Panel(); this.label_nextimage = new System.Windows.Forms.Label(); this.cb_loop = new System.Windows.Forms.CheckBox(); @@ -60,7 +60,7 @@ this.pictureBox_rximage = new System.Windows.Forms.PictureBox(); this.pictureBox_tximage = new System.Windows.Forms.PictureBox(); this.tabControl1 = new System.Windows.Forms.TabControl(); - this.tabPage3 = new System.Windows.Forms.TabPage(); + this.tabPage_file = new System.Windows.Forms.TabPage(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.button2 = new System.Windows.Forms.Button(); this.bt_openrxfile = new System.Windows.Forms.Button(); @@ -95,13 +95,13 @@ this.label10 = new System.Windows.Forms.Label(); this.cb_mic = new System.Windows.Forms.ComboBox(); this.label11 = new System.Windows.Forms.Label(); - this.tabPage5 = new System.Windows.Forms.TabPage(); + this.tabPage_setup = new System.Windows.Forms.TabPage(); this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.cb_language = new System.Windows.Forms.ComboBox(); this.cb_autostart = new System.Windows.Forms.CheckBox(); this.bt_shutdown = new System.Windows.Forms.Button(); this.tb_shutdown = new System.Windows.Forms.TextBox(); this.bt_resetmodem = new System.Windows.Forms.Button(); - this.textBox2 = new System.Windows.Forms.TextBox(); this.textBox3 = new System.Windows.Forms.TextBox(); this.groupBox3 = new System.Windows.Forms.GroupBox(); this.pb_audioCAPstatus = new System.Windows.Forms.PictureBox(); @@ -125,7 +125,7 @@ this.tb_callsign = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.cb_stampcall = new System.Windows.Forms.CheckBox(); - this.tabPage4 = new System.Windows.Forms.TabPage(); + this.tabPage_about = new System.Windows.Forms.TabPage(); this.richTextBox1 = new System.Windows.Forms.RichTextBox(); this.cb_speed = new System.Windows.Forms.ComboBox(); this.label_speed = new System.Windows.Forms.Label(); @@ -140,13 +140,13 @@ this.pb_rxsync = new System.Windows.Forms.PictureBox(); this.pb_rxsignal = new System.Windows.Forms.PictureBox(); this.statusStrip1.SuspendLayout(); - this.tabPage1.SuspendLayout(); - this.tabPage2.SuspendLayout(); + this.tabPage_ber.SuspendLayout(); + this.tabPage_image.SuspendLayout(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_rximage)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_tximage)).BeginInit(); this.tabControl1.SuspendLayout(); - this.tabPage3.SuspendLayout(); + this.tabPage_file.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.tabPage_audio.SuspendLayout(); this.groupBox7.SuspendLayout(); @@ -158,7 +158,7 @@ ((System.ComponentModel.ISupportInitialize)(this.pb_voicePBstatus)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_mic)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_loadspeaker)).BeginInit(); - this.tabPage5.SuspendLayout(); + this.tabPage_setup.SuspendLayout(); this.groupBox4.SuspendLayout(); this.groupBox3.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pb_audioCAPstatus)).BeginInit(); @@ -166,7 +166,7 @@ ((System.ComponentModel.ISupportInitialize)(this.tb_CAPvol)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_PBvol)).BeginInit(); this.groupBox2.SuspendLayout(); - this.tabPage4.SuspendLayout(); + this.tabPage_about.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pb_rxsync)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pb_rxsignal)).BeginInit(); this.SuspendLayout(); @@ -235,19 +235,19 @@ this.panel_txspectrum.TabIndex = 6; this.panel_txspectrum.Paint += new System.Windows.Forms.PaintEventHandler(this.panel_txspectrum_Paint); // - // tabPage1 + // tabPage_ber // - this.tabPage1.Controls.Add(this.button_stopBERtest); - this.tabPage1.Controls.Add(this.button_startBERtest); - this.tabPage1.Controls.Add(this.rtb); - this.tabPage1.ImageIndex = 4; - this.tabPage1.Location = new System.Drawing.Point(4, 23); - this.tabPage1.Name = "tabPage1"; - this.tabPage1.Padding = new System.Windows.Forms.Padding(3); - this.tabPage1.Size = new System.Drawing.Size(1291, 552); - this.tabPage1.TabIndex = 0; - this.tabPage1.Text = "BER Test"; - this.tabPage1.UseVisualStyleBackColor = true; + this.tabPage_ber.Controls.Add(this.button_stopBERtest); + this.tabPage_ber.Controls.Add(this.button_startBERtest); + this.tabPage_ber.Controls.Add(this.rtb); + this.tabPage_ber.ImageIndex = 4; + this.tabPage_ber.Location = new System.Drawing.Point(4, 23); + this.tabPage_ber.Name = "tabPage_ber"; + this.tabPage_ber.Padding = new System.Windows.Forms.Padding(3); + this.tabPage_ber.Size = new System.Drawing.Size(1291, 552); + this.tabPage_ber.TabIndex = 0; + this.tabPage_ber.Text = "BER Test"; + this.tabPage_ber.UseVisualStyleBackColor = true; // // button_stopBERtest // @@ -304,21 +304,21 @@ this.rtb.TabIndex = 0; this.rtb.Text = ""; // - // tabPage2 + // tabPage_image // - this.tabPage2.Controls.Add(this.groupBox1); - this.tabPage2.Controls.Add(this.label_rximage); - this.tabPage2.Controls.Add(this.label_tximage); - this.tabPage2.Controls.Add(this.pictureBox_rximage); - this.tabPage2.Controls.Add(this.pictureBox_tximage); - this.tabPage2.ImageIndex = 3; - this.tabPage2.Location = new System.Drawing.Point(4, 23); - this.tabPage2.Name = "tabPage2"; - this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(1291, 552); - this.tabPage2.TabIndex = 1; - this.tabPage2.Text = "Image"; - this.tabPage2.UseVisualStyleBackColor = true; + this.tabPage_image.Controls.Add(this.groupBox1); + this.tabPage_image.Controls.Add(this.label_rximage); + this.tabPage_image.Controls.Add(this.label_tximage); + this.tabPage_image.Controls.Add(this.pictureBox_rximage); + this.tabPage_image.Controls.Add(this.pictureBox_tximage); + this.tabPage_image.ImageIndex = 3; + this.tabPage_image.Location = new System.Drawing.Point(4, 23); + this.tabPage_image.Name = "tabPage_image"; + this.tabPage_image.Padding = new System.Windows.Forms.Padding(3); + this.tabPage_image.Size = new System.Drawing.Size(1291, 552); + this.tabPage_image.TabIndex = 1; + this.tabPage_image.Text = "Image"; + this.tabPage_image.UseVisualStyleBackColor = true; // // groupBox1 // @@ -375,6 +375,7 @@ this.button_loadimage.ImageList = this.imageList1; this.button_loadimage.Location = new System.Drawing.Point(265, 5); this.button_loadimage.Name = "button_loadimage"; + this.button_loadimage.RightToLeft = System.Windows.Forms.RightToLeft.No; this.button_loadimage.Size = new System.Drawing.Size(88, 23); this.button_loadimage.TabIndex = 0; this.button_loadimage.Text = " Load Image"; @@ -411,9 +412,9 @@ this.checkBox_big.CheckState = System.Windows.Forms.CheckState.Checked; this.checkBox_big.Location = new System.Drawing.Point(187, 9); this.checkBox_big.Name = "checkBox_big"; - this.checkBox_big.Size = new System.Drawing.Size(75, 17); + this.checkBox_big.Size = new System.Drawing.Size(79, 17); this.checkBox_big.TabIndex = 8; - this.checkBox_big.Text = "big picture"; + this.checkBox_big.Text = "640(320)px"; this.checkBox_big.UseVisualStyleBackColor = true; this.checkBox_big.CheckedChanged += new System.EventHandler(this.checkBox_small_CheckedChanged); // @@ -427,7 +428,7 @@ this.button_cancelimg.Name = "button_cancelimg"; this.button_cancelimg.Size = new System.Drawing.Size(75, 23); this.button_cancelimg.TabIndex = 9; - this.button_cancelimg.Text = " Cancel"; + this.button_cancelimg.Text = " Cancel"; this.button_cancelimg.UseVisualStyleBackColor = true; this.button_cancelimg.Click += new System.EventHandler(this.button_cancelimg_Click); // @@ -468,7 +469,7 @@ // // pictureBox_rximage // - this.pictureBox_rximage.BackgroundImage = global::oscardata.Properties.Resources.image1; + this.pictureBox_rximage.BackgroundImage = global::oscardata.Properties.Resources.hintergrundxcf; this.pictureBox_rximage.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; this.pictureBox_rximage.Location = new System.Drawing.Point(642, 27); this.pictureBox_rximage.Name = "pictureBox_rximage"; @@ -479,7 +480,7 @@ // // pictureBox_tximage // - this.pictureBox_tximage.BackgroundImage = global::oscardata.Properties.Resources.image; + this.pictureBox_tximage.BackgroundImage = global::oscardata.Properties.Resources.hintergrundxcf; this.pictureBox_tximage.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; this.pictureBox_tximage.Location = new System.Drawing.Point(1, 27); this.pictureBox_tximage.Name = "pictureBox_tximage"; @@ -489,12 +490,12 @@ // // tabControl1 // - this.tabControl1.Controls.Add(this.tabPage2); - this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage_image); + this.tabControl1.Controls.Add(this.tabPage_file); this.tabControl1.Controls.Add(this.tabPage_audio); - this.tabControl1.Controls.Add(this.tabPage1); - this.tabControl1.Controls.Add(this.tabPage5); - this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Controls.Add(this.tabPage_ber); + this.tabControl1.Controls.Add(this.tabPage_setup); + this.tabControl1.Controls.Add(this.tabPage_about); this.tabControl1.ImageList = this.imageList1; this.tabControl1.Location = new System.Drawing.Point(5, 3); this.tabControl1.Name = "tabControl1"; @@ -502,26 +503,26 @@ this.tabControl1.Size = new System.Drawing.Size(1299, 579); this.tabControl1.TabIndex = 3; // - // tabPage3 + // tabPage_file // - this.tabPage3.Controls.Add(this.pictureBox1); - this.tabPage3.Controls.Add(this.button2); - this.tabPage3.Controls.Add(this.bt_openrxfile); - this.tabPage3.Controls.Add(this.label_rxfile); - this.tabPage3.Controls.Add(this.label_txfile); - this.tabPage3.Controls.Add(this.rtb_RXfile); - this.tabPage3.Controls.Add(this.rtb_TXfile); - this.tabPage3.Controls.Add(this.bt_file_send); - this.tabPage3.Controls.Add(this.bt_sendBinaryFile); - this.tabPage3.Controls.Add(this.bt_file_html); - this.tabPage3.Controls.Add(this.bt_file_ascii); - this.tabPage3.ImageIndex = 9; - this.tabPage3.Location = new System.Drawing.Point(4, 23); - this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(1291, 552); - this.tabPage3.TabIndex = 2; - this.tabPage3.Text = "File"; - this.tabPage3.UseVisualStyleBackColor = true; + this.tabPage_file.Controls.Add(this.pictureBox1); + this.tabPage_file.Controls.Add(this.button2); + this.tabPage_file.Controls.Add(this.bt_openrxfile); + this.tabPage_file.Controls.Add(this.label_rxfile); + this.tabPage_file.Controls.Add(this.label_txfile); + this.tabPage_file.Controls.Add(this.rtb_RXfile); + this.tabPage_file.Controls.Add(this.rtb_TXfile); + this.tabPage_file.Controls.Add(this.bt_file_send); + this.tabPage_file.Controls.Add(this.bt_sendBinaryFile); + this.tabPage_file.Controls.Add(this.bt_file_html); + this.tabPage_file.Controls.Add(this.bt_file_ascii); + this.tabPage_file.ImageIndex = 9; + this.tabPage_file.Location = new System.Drawing.Point(4, 23); + this.tabPage_file.Name = "tabPage_file"; + this.tabPage_file.Size = new System.Drawing.Size(1291, 552); + this.tabPage_file.TabIndex = 2; + this.tabPage_file.Text = "File"; + this.tabPage_file.UseVisualStyleBackColor = true; // // pictureBox1 // @@ -682,9 +683,9 @@ this.rb_codec2.AutoSize = true; this.rb_codec2.Location = new System.Drawing.Point(92, 50); this.rb_codec2.Name = "rb_codec2"; - this.rb_codec2.Size = new System.Drawing.Size(289, 17); + this.rb_codec2.Size = new System.Drawing.Size(342, 17); this.rb_codec2.TabIndex = 23; - this.rb_codec2.Text = "CODEC-2 parametric audio codec. Audio rate: 3200 bps"; + this.rb_codec2.Text = "CODEC-2 parametric audio codec. For QPSK. Audio rate: 3200 bps"; this.rb_codec2.UseVisualStyleBackColor = true; // // pictureBox2 @@ -703,10 +704,10 @@ this.rb_opus.Checked = true; this.rb_opus.Location = new System.Drawing.Point(92, 27); this.rb_opus.Name = "rb_opus"; - this.rb_opus.Size = new System.Drawing.Size(290, 17); + this.rb_opus.Size = new System.Drawing.Size(348, 17); this.rb_opus.TabIndex = 0; this.rb_opus.TabStop = true; - this.rb_opus.Text = "OPUS rate adaptive codec. Audio rate: 84% of data rate"; + this.rb_opus.Text = "OPUS rate adaptive codec. For 8APSK. Audio rate: 84% of data rate"; this.rb_opus.UseVisualStyleBackColor = true; // // groupBox6 @@ -910,34 +911,47 @@ this.label11.TabIndex = 10; this.label11.Text = "Microphone:"; // - // tabPage5 + // tabPage_setup // - this.tabPage5.Controls.Add(this.groupBox4); - this.tabPage5.Controls.Add(this.groupBox3); - this.tabPage5.Controls.Add(this.groupBox2); - this.tabPage5.ImageIndex = 6; - this.tabPage5.Location = new System.Drawing.Point(4, 23); - this.tabPage5.Name = "tabPage5"; - this.tabPage5.Size = new System.Drawing.Size(1291, 552); - this.tabPage5.TabIndex = 4; - this.tabPage5.Text = "Setup"; - this.tabPage5.UseVisualStyleBackColor = true; + this.tabPage_setup.Controls.Add(this.groupBox4); + this.tabPage_setup.Controls.Add(this.groupBox3); + this.tabPage_setup.Controls.Add(this.groupBox2); + this.tabPage_setup.ImageIndex = 6; + this.tabPage_setup.Location = new System.Drawing.Point(4, 23); + this.tabPage_setup.Name = "tabPage_setup"; + this.tabPage_setup.Size = new System.Drawing.Size(1291, 552); + this.tabPage_setup.TabIndex = 4; + this.tabPage_setup.Text = "Setup"; + this.tabPage_setup.UseVisualStyleBackColor = true; // // groupBox4 // + this.groupBox4.Controls.Add(this.cb_language); this.groupBox4.Controls.Add(this.cb_autostart); this.groupBox4.Controls.Add(this.bt_shutdown); this.groupBox4.Controls.Add(this.tb_shutdown); this.groupBox4.Controls.Add(this.bt_resetmodem); - this.groupBox4.Controls.Add(this.textBox2); this.groupBox4.Controls.Add(this.textBox3); this.groupBox4.Location = new System.Drawing.Point(12, 259); this.groupBox4.Name = "groupBox4"; - this.groupBox4.Size = new System.Drawing.Size(674, 105); + this.groupBox4.Size = new System.Drawing.Size(674, 121); this.groupBox4.TabIndex = 15; this.groupBox4.TabStop = false; this.groupBox4.Text = "Maintenance"; // + // cb_language + // + this.cb_language.FormattingEnabled = true; + this.cb_language.Items.AddRange(new object[] { + "English", + "German/Deutsch"}); + this.cb_language.Location = new System.Drawing.Point(207, 19); + this.cb_language.Name = "cb_language"; + this.cb_language.Size = new System.Drawing.Size(110, 21); + this.cb_language.TabIndex = 24; + this.cb_language.Text = "English"; + this.cb_language.SelectedIndexChanged += new System.EventHandler(this.cb_language_SelectedIndexChanged); + // // cb_autostart // this.cb_autostart.AutoSize = true; @@ -949,6 +963,7 @@ this.cb_autostart.TabIndex = 4; this.cb_autostart.Text = "AUTO start/stop HSmodem"; this.cb_autostart.UseVisualStyleBackColor = true; + this.cb_autostart.CheckedChanged += new System.EventHandler(this.cb_autostart_CheckedChanged); // // bt_shutdown // @@ -974,7 +989,7 @@ // // bt_resetmodem // - this.bt_resetmodem.Location = new System.Drawing.Point(183, 17); + this.bt_resetmodem.Location = new System.Drawing.Point(356, 82); this.bt_resetmodem.Name = "bt_resetmodem"; this.bt_resetmodem.Size = new System.Drawing.Size(117, 23); this.bt_resetmodem.TabIndex = 6; @@ -983,19 +998,6 @@ this.bt_resetmodem.Visible = false; this.bt_resetmodem.Click += new System.EventHandler(this.bt_resetmodem_Click); // - // textBox2 - // - this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.textBox2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBox2.ForeColor = System.Drawing.Color.Black; - this.textBox2.Location = new System.Drawing.Point(183, 46); - this.textBox2.Multiline = true; - this.textBox2.Name = "textBox2"; - this.textBox2.Size = new System.Drawing.Size(126, 50); - this.textBox2.TabIndex = 11; - this.textBox2.Text = "in case the RX has sync\r\nproblems, it can be\r\nre-initialized here."; - this.textBox2.Visible = false; - // // textBox3 // this.textBox3.BorderStyle = System.Windows.Forms.BorderStyle.None; @@ -1075,7 +1077,7 @@ this.tb_CAPvol.Name = "tb_CAPvol"; this.tb_CAPvol.Size = new System.Drawing.Size(100, 24); this.tb_CAPvol.TabIndex = 14; - this.tb_CAPvol.TickStyle = System.Windows.Forms.TickStyle.None; + this.tb_CAPvol.TickFrequency = 10; this.tb_CAPvol.Value = 50; this.tb_CAPvol.Scroll += new System.EventHandler(this.tb_CAPvol_Scroll); // @@ -1089,7 +1091,7 @@ this.tb_PBvol.Name = "tb_PBvol"; this.tb_PBvol.Size = new System.Drawing.Size(100, 24); this.tb_PBvol.TabIndex = 13; - this.tb_PBvol.TickStyle = System.Windows.Forms.TickStyle.None; + this.tb_PBvol.TickFrequency = 10; this.tb_PBvol.Value = 50; this.tb_PBvol.Scroll += new System.EventHandler(this.tb_PBvol_Scroll); // @@ -1263,16 +1265,16 @@ this.cb_stampcall.Text = "Insert Callsign into picture"; this.cb_stampcall.UseVisualStyleBackColor = true; // - // tabPage4 + // tabPage_about // - this.tabPage4.Controls.Add(this.richTextBox1); - this.tabPage4.ImageIndex = 12; - this.tabPage4.Location = new System.Drawing.Point(4, 23); - this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(1291, 552); - this.tabPage4.TabIndex = 6; - this.tabPage4.Text = "About"; - this.tabPage4.UseVisualStyleBackColor = true; + this.tabPage_about.Controls.Add(this.richTextBox1); + this.tabPage_about.ImageIndex = 12; + this.tabPage_about.Location = new System.Drawing.Point(4, 23); + this.tabPage_about.Name = "tabPage_about"; + this.tabPage_about.Size = new System.Drawing.Size(1291, 552); + this.tabPage_about.TabIndex = 6; + this.tabPage_about.Text = "About"; + this.tabPage_about.UseVisualStyleBackColor = true; // // richTextBox1 // @@ -1426,20 +1428,20 @@ this.ForeColor = System.Drawing.SystemColors.ControlText; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "Form1"; - this.Text = "QO-100 NB Transponder HS Multimedia Modem AMSAT-DL V0.4 by DJ0ABR"; + this.Text = "QO-100 NB Transponder HS Multimedia Modem AMSAT-DL V0.44 by DJ0ABR"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); - this.tabPage1.ResumeLayout(false); - this.tabPage2.ResumeLayout(false); - this.tabPage2.PerformLayout(); + this.tabPage_ber.ResumeLayout(false); + this.tabPage_image.ResumeLayout(false); + this.tabPage_image.PerformLayout(); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_rximage)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox_tximage)).EndInit(); this.tabControl1.ResumeLayout(false); - this.tabPage3.ResumeLayout(false); - this.tabPage3.PerformLayout(); + this.tabPage_file.ResumeLayout(false); + this.tabPage_file.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.tabPage_audio.ResumeLayout(false); this.groupBox7.ResumeLayout(false); @@ -1454,7 +1456,7 @@ ((System.ComponentModel.ISupportInitialize)(this.pb_voicePBstatus)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_mic)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.tb_loadspeaker)).EndInit(); - this.tabPage5.ResumeLayout(false); + this.tabPage_setup.ResumeLayout(false); this.groupBox4.ResumeLayout(false); this.groupBox4.PerformLayout(); this.groupBox3.ResumeLayout(false); @@ -1465,7 +1467,7 @@ ((System.ComponentModel.ISupportInitialize)(this.tb_PBvol)).EndInit(); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); - this.tabPage4.ResumeLayout(false); + this.tabPage_about.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.pb_rxsync)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pb_rxsignal)).EndInit(); this.ResumeLayout(false); @@ -1482,11 +1484,11 @@ private System.Windows.Forms.Panel panel_constel; private System.Windows.Forms.Timer timer_qpsk; private System.Windows.Forms.Panel panel_txspectrum; - private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage_ber; private System.Windows.Forms.Button button_stopBERtest; private System.Windows.Forms.Button button_startBERtest; private System.Windows.Forms.RichTextBox rtb; - private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.TabPage tabPage_image; private System.Windows.Forms.ComboBox comboBox_quality; private System.Windows.Forms.Button button_loadimage; private System.Windows.Forms.Button button_cancelimg; @@ -1500,7 +1502,7 @@ private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.ToolStripStatusLabel ts_ip; private System.Windows.Forms.Panel groupBox1; - private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.TabPage tabPage_file; private System.Windows.Forms.RichTextBox rtb_TXfile; private System.Windows.Forms.Button bt_file_send; private System.Windows.Forms.Button bt_sendBinaryFile; @@ -1518,7 +1520,7 @@ private System.Windows.Forms.CheckBox cb_loop; private System.Windows.Forms.Label label_nextimage; private System.Windows.Forms.Button button2; - private System.Windows.Forms.TabPage tabPage5; + private System.Windows.Forms.TabPage tabPage_setup; private System.Windows.Forms.TextBox tb_callsign; private System.Windows.Forms.Label label1; private System.Windows.Forms.CheckBox cb_stampcall; @@ -1529,7 +1531,6 @@ private System.Windows.Forms.ComboBox cb_audioCAP; private System.Windows.Forms.Label label3; private System.Windows.Forms.ComboBox cb_audioPB; - private System.Windows.Forms.TextBox textBox2; private System.Windows.Forms.GroupBox groupBox4; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.GroupBox groupBox2; @@ -1569,7 +1570,7 @@ private System.Windows.Forms.ImageList imageList1; private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.PictureBox pictureBox2; - private System.Windows.Forms.TabPage tabPage4; + private System.Windows.Forms.TabPage tabPage_about; private System.Windows.Forms.RichTextBox richTextBox1; private System.Windows.Forms.PictureBox pb_voiceCAPstatus; private System.Windows.Forms.PictureBox pb_voicePBstatus; @@ -1584,6 +1585,7 @@ private System.Windows.Forms.Label lb_rxsignal; private System.Windows.Forms.Label lb_rxsync; private System.Windows.Forms.PictureBox pb_rxsync; + private System.Windows.Forms.ComboBox cb_language; } } diff --git a/oscardata/oscardata/Form1.cs b/oscardata/oscardata/Form1.cs index 1719eab..7cf360a 100755 --- a/oscardata/oscardata/Form1.cs +++ b/oscardata/oscardata/Form1.cs @@ -54,10 +54,10 @@ namespace oscardata InitializeComponent(); // needed for ARM mono, which cannot load a picbox directly from file - var bmp = new Bitmap(Resources.image); + var bmp = new Bitmap(Resources.hintergrundxcf); pictureBox_rximage.BackgroundImage = bmp; - bmp = new Bitmap(Resources.image1); + bmp = new Bitmap(Resources.hintergrundxcf); pictureBox_tximage.BackgroundImage = bmp; // if this program was started from another loacation @@ -79,7 +79,7 @@ namespace oscardata OperatingSystem osversion = System.Environment.OSVersion; statics.OSversion = osversion.Platform.ToString(); if (osversion.VersionString.Contains("indow")) - statics.ostype = 0; + statics.ostype = 0; // Win$ else statics.ostype = 1; // Linux @@ -91,6 +91,7 @@ namespace oscardata statics.jpg_tempfilename = statics.addTmpPath(statics.jpg_tempfilename); load_Setup(); + cb_language_SelectedIndexChanged(null, null); if (cb_autostart.Checked) { @@ -101,11 +102,10 @@ namespace oscardata checkBox_small_CheckedChanged(null, null); // init speed - comboBox1_SelectedIndexChanged(null,null); + comboBox1_SelectedIndexChanged(null, null); // create Udp Communication ports and init UDP system Udp.InitUdp(); - search_modem(); ArraySend.ArraySendInit(); // enable processing @@ -176,7 +176,7 @@ namespace oscardata // after an image was finished, wait before starting the new one // this helps cleaning any buffer int spacetime = 20000; // ms - label_nextimage.Text = "next image in " + ((spacetime / timer_udpTX.Interval - loopdelay) / 10).ToString() + " s"; + label_nextimage.Text = langstr[0] + ((spacetime / timer_udpTX.Interval - loopdelay) / 10).ToString() + " s"; if (++loopdelay > (spacetime / timer_udpTX.Interval)) { // start sending a new picture @@ -186,7 +186,7 @@ namespace oscardata else { loopdelay = 0; - label_nextimage.Text = "transmitting"; + label_nextimage.Text = langstr[1]; } } else @@ -289,15 +289,15 @@ namespace oscardata if (last_initAudioStatus != statics.initAudioStatus) { - if ((statics.initAudioStatus & 1) == 1) - pb_audioPBstatus.BackgroundImage = Properties.Resources.fail; - else + if ((statics.initAudioStatus & 1) == 1) pb_audioPBstatus.BackgroundImage = Properties.Resources.ok; + else + pb_audioPBstatus.BackgroundImage = Properties.Resources.fail; - if ((statics.initAudioStatus & 2) == 2) - pb_audioCAPstatus.BackgroundImage = Properties.Resources.fail; - else + if ((statics.initAudioStatus & 2) == 2) pb_audioCAPstatus.BackgroundImage = Properties.Resources.ok; + else + pb_audioCAPstatus.BackgroundImage = Properties.Resources.fail; last_initAudioStatus = statics.initAudioStatus; } @@ -305,14 +305,14 @@ namespace oscardata if (last_initVoiceStatus != statics.initVoiceStatus) { if ((statics.initVoiceStatus & 1) == 1) - pb_voicePBstatus.BackgroundImage = Properties.Resources.fail; - else pb_voicePBstatus.BackgroundImage = Properties.Resources.ok; + else + pb_voicePBstatus.BackgroundImage = Properties.Resources.fail; if ((statics.initVoiceStatus & 2) == 2) - pb_voiceCAPstatus.BackgroundImage = Properties.Resources.fail; - else pb_voiceCAPstatus.BackgroundImage = Properties.Resources.ok; + else + pb_voiceCAPstatus.BackgroundImage = Properties.Resources.fail; last_initVoiceStatus = statics.initVoiceStatus; } @@ -359,39 +359,44 @@ namespace oscardata if (cb_autostart.Checked) { - // tell hsmodem to terminate itself - Byte[] txdata = new byte[1]; - txdata[0] = (Byte)statics.terminate; - Udp.UdpSendCtrl(txdata); - - Thread.Sleep(250); - - if (statics.ostype == 0) - { - int to = 0; - while(statics.isProcRunning("hsmodem.exe")) - { - Thread.Sleep(250); - // tell hsmodem to terminate itself - Udp.UdpSendCtrl(txdata); - if (++to >= 10) break; // give up after 2,5s - } - - if (to >= 10) - statics.killall("hsmodem.exe"); - } - else - { - Thread.Sleep(250); - statics.killall("hsmodem"); - } - + killLocalModem(); } // exit the threads statics.running = false; Udp.Close(); } + void killLocalModem() + { + // tell hsmodem to terminate itself + Byte[] txdata = new byte[1]; + txdata[0] = (Byte)statics.terminate; + Udp.UdpSendCtrl(txdata); + + Thread.Sleep(250); + + // if that did not work, kill it directly + if (statics.ostype == 0) + { + int to = 0; + while (statics.isProcRunning("hsmodem.exe")) + { + Thread.Sleep(250); + // tell hsmodem to terminate itself + Udp.UdpSendCtrl(txdata); + if (++to >= 10) break; // give up after 2,5s + } + + if (to >= 10) + statics.killall("hsmodem.exe"); + } + else + { + Thread.Sleep(250); + statics.killall("hsmodem"); + } + } + // RX timer int rxstat = 0; int speed; @@ -428,7 +433,7 @@ namespace oscardata // handle file receive if (rxtype == statics.Image) { - if (recfile.receive(rxd)) + if (recfile.receive(rxd) == 1) { if (recfile.filename != null && recfile.filename.Length > 0 && minfo != statics.FirstFrame) { @@ -451,17 +456,21 @@ namespace oscardata if (rxtype == statics.AsciiFile) { - if(recfile.receive(rxd)) + int fret = recfile.receive(rxd); + if (fret == 1) { // ASCII file received, show in window String serg = File.ReadAllText(recfile.filename); printText(rtb_RXfile, serg); } + if (fret == -5) + printBadBlocks(); } if (rxtype == statics.HTMLFile) { - if (recfile.receive(rxd)) + int fret = recfile.receive(rxd); + if (fret == 1) { // HTML file received, show in window String serg = File.ReadAllText(recfile.filename); @@ -469,24 +478,36 @@ namespace oscardata // and show in browser OpenUrl(recfile.filename); } + if (fret == -5) + printBadBlocks(); } if (rxtype == statics.BinaryFile) { - if (recfile.receive(rxd)) + int fret = recfile.receive(rxd); + if (fret == 1) { // Binary file received, show statistics in window - printText(rtb_RXfile, "binary file received\r\n"); - printText(rtb_RXfile, "--------------------\r\n\r\n"); - printText(rtb_RXfile, "transmission time : " + ((int)recfile.runtime.TotalSeconds).ToString() + " seconds" + "\r\n\r\n"); - printText(rtb_RXfile, "transmission speed: " + ((int)(recfile.filesize * 8 / recfile.runtime.TotalSeconds)).ToString() + " bit/s" + "\r\n\r\n"); - printText(rtb_RXfile, "file size : " + recfile.filesize + " byte\r\n\r\n"); - printText(rtb_RXfile, "file name : " + recfile.filename + "\r\n\r\n"); - if(recfile.filename.Length <= 1) + try { - printText(rtb_RXfile, "file status : not complete, retransmit\r\n\r\n"); + printText(rtb_RXfile, langstr[2]); + printText(rtb_RXfile, "--------------------\r\n\r\n"); + printText(rtb_RXfile, langstr[3] + ((int)recfile.runtime.TotalSeconds).ToString() + " seconds" + "\r\n\r\n"); + printText(rtb_RXfile, langstr[4] + ((int)(recfile.filesize * 8 / recfile.runtime.TotalSeconds)).ToString() + " bit/s" + "\r\n\r\n"); + printText(rtb_RXfile, langstr[5] + recfile.filesize + " byte\r\n\r\n"); + printText(rtb_RXfile, langstr[6] + recfile.filename + "\r\n\r\n"); + if (recfile.filename.Length <= 1) + { + printText(rtb_RXfile, langstr[7]); + } + } + catch + { + printText(rtb_RXfile, "RX error\r\n"); } } + if (fret == -5) + printBadBlocks(); } // ===== BER Test ================================================ @@ -499,6 +520,26 @@ namespace oscardata } } + void printBadBlocks() + { + rtb_RXfile.Text = ""; + printText(rtb_RXfile, langstr[2]); + printText(rtb_RXfile, "--------------------\r\n\r\n"); + printText(rtb_RXfile, langstr[31] + "\r\n\r\n"); + + int[] d = new int[2]; + recfile.oldblockinfo(d); + int failed = d[0] - d[1]; + + String s = "\n" + langstr[25] + + "-------------------\n" + + "total : " + (d[0]+1) + "\n" + + langstr[26] + (d[1]+1) + "\n" + + langstr[27] + failed + "\n"; + printText(rtb_RXfile, s + "\r\n\r\n"); + printText(rtb_RXfile, langstr[32] + ": " + recfile.missingBlockString()); + } + private void OpenUrl(string url) { try @@ -595,12 +636,12 @@ namespace oscardata } // Title - e.Graphics.DrawString("Tuning Window", fnt, Brushes.Black, GetFFTPos(110, 3000)); + e.Graphics.DrawString(langstr[8], fnt, Brushes.Black, GetFFTPos(110, 3000)); e.Graphics.DrawString(miny.ToString() + " Hz", smallfnt, Brushes.Black, GetFFTPos(5, 2800)); e.Graphics.DrawString("1500 Hz", smallfnt, Brushes.Black, GetFFTPos(138, 680)); e.Graphics.DrawString(maxy.ToString() + " Hz", smallfnt, Brushes.Black, GetFFTPos(270, 2800)); - e.Graphics.DrawString("min Level", smallfnt, Brushes.Black, GetFFTPos(290, 1000)); + e.Graphics.DrawString(langstr[9], smallfnt, Brushes.Black, GetFFTPos(290, 1000)); e.Graphics.DrawString("max", smallfnt, Brushes.Black, GetFFTPos(290, 2450)); while (true) @@ -788,9 +829,9 @@ namespace oscardata void ShowTXstatus() { if(txcommand == statics.Image) - label_tximage.Text = "TX image: " + TXRealFilename + ". Sent: " + (ArraySend.txpos / 1000).ToString() + " of " + (TXRealFileSize / 1000).ToString() + " kB"; + label_tximage.Text = langstr[10] + TXRealFilename + langstr[11] + (ArraySend.txpos / 1000).ToString() + langstr[30] + (TXRealFileSize / 1000).ToString() + " kB"; else - label_txfile.Text = "TX file: " + TXRealFilename + ". Sent: " + (ArraySend.txpos / 1000).ToString() + " of " + (TXRealFileSize / 1000).ToString() + " kB"; + label_txfile.Text = langstr[12] + TXRealFilename + langstr[11] + (ArraySend.txpos / 1000).ToString() + langstr[30] + (TXRealFileSize / 1000).ToString() + " kB"; } // in loop mode only: send the next picture in current image folder @@ -832,7 +873,7 @@ namespace oscardata private void button_loadimage_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); - open.Filter = "Image Files(*.jpg; *.jpeg; *.png; *.gif; *.bmp)|*.jpg; *.jpeg; *.png; *.gif; *.bmp"; + open.Filter = langstr[13]; if (open.ShowDialog() == DialogResult.OK) { prepareImage(open.FileName); @@ -884,9 +925,9 @@ namespace oscardata // show RX status for this frame if (rxstat == 4) - line += " frame lost"; + line += langstr[14]; else - line += " sequence OK"; + line += langstr[29]; int bits = rxframecounter * 258 * 8; int bytes = rxframecounter * 258; @@ -896,23 +937,23 @@ namespace oscardata if (bits > 1000) { bits /= 1000; - sbit = "kb"; + sbit = "kbit"; } if (bits > 1000) { bits /= 1000; - sbit = "Mb"; + sbit = "Mbit"; } if (bytes > 1000) { bytes /= 1000; - sbyt = "kB"; + sbyt = "kByte"; } if (bytes > 1000) { bytes /= 1000; - sbyt = "MB"; + sbyt = "MByte"; } line += " " + bits.ToString() + " " + sbit + " " + bytes.ToString() + " " + sbyt; @@ -951,12 +992,12 @@ namespace oscardata if (ArraySend.rxFilename != null && ArraySend.rxFilename.Length > 0) { s += ArraySend.rxFilename + " "; - s += recfile.rxbytes / 1000 + " of " + ArraySend.FileSize / 1000 + " kB "; + s += recfile.rxbytes / 1000 + langstr[30] + ArraySend.FileSize / 1000 + " kB "; s += Math.Truncate(recfile.runtime.TotalSeconds) + " s, "; - s += blockres[1] + " of " + blockres[0] + " blocks OK"; + s += blockres[1] + langstr[30] + blockres[0] + langstr[15]; } else - s += "wait for RX"; + s += langstr[16]; if (rxtype == statics.Image) label_rximage.Text = s; @@ -965,24 +1006,24 @@ namespace oscardata label_rxfile.Text = s; // show speed in status line at the left side - toolStripStatusLabel.Text = "Line Speed: " + speed.ToString() + " bps"; + toolStripStatusLabel.Text = langstr[17] + speed.ToString() + " bps"; if (missBlocks < 0) missBlocks = 0; if (missingBlocks < 0) missingBlocks = 0; // show RX status in the status line if (rxtype == statics.BERtest) - RXstatus.Text = "RXed: " + rxbytecounter + " Byte. Missing blocks: " + missBlocks; + RXstatus.Text = "RX: " + rxbytecounter + langstr[18] + missBlocks; else { if(fsz > 0) - RXstatus.Text = "RXed: " + fsz + " Byte. Missing blocks: " + missingBlocks; + RXstatus.Text = "RX: " + fsz + langstr[18] + missingBlocks; else - RXstatus.Text = "RXed: " + rxbytecounter + " Byte. Missing blocks: " + missingBlocks; + RXstatus.Text = "RX: " + rxbytecounter + langstr[18] + missingBlocks; } if(speed_bps > 0) - RXstatus.Text += " Net Speed:" + speed_bps + " bps"; + RXstatus.Text += langstr[19] + speed_bps + " bps"; } private void button_cancelimg_Click(object sender, EventArgs e) @@ -1079,23 +1120,7 @@ namespace oscardata } return ip; } - - Byte getPBaudioDevice() - { - String s = cb_audioPB.Text; - Byte x = (Byte)cb_audioPB.Items.IndexOf(s); - //if (s.ToUpper() == "DEFAULT") x = 255; - return x; - } - - Byte getCAPaudioDevice() - { - String s = cb_audioCAP.Text; - Byte x = (Byte)cb_audioCAP.Items.IndexOf(s); - //if (s.ToUpper() == "DEFAULT") x = 255; - return x; - } - + Byte getLSaudioDevice() { String s = cb_loudspeaker.Text; @@ -1120,19 +1145,52 @@ namespace oscardata * if a modem receives this message, it returns with an * UDP message to UdpBCport containing a String with it's IP address * this message also contains the selected Audio Devices + * + * Format: + * Byte: + * 0 ... 0x3c + * 1 ... PB volume + * 2 ... CAP volume + * 3 ... announcement on/off, duration + * 4 ... DV loudspeaker volume + * 5 ... DV mic volume + * 6..9 ... unused + * 10 .. 109 ... PB device name + * 110 .. 209 ... CAP device name + * */ private void search_modem() { - Byte[] txb = new byte[8]; + Byte[] txb = new byte[210]; txb[0] = 0x3c; // ID of this message - txb[1] = getPBaudioDevice(); - txb[2] = getCAPaudioDevice(); - txb[3] = (Byte)tb_PBvol.Value; - txb[4] = (Byte)tb_CAPvol.Value; - txb[5] = (Byte)cb_announcement.Items.IndexOf(cb_announcement.Text); - txb[6] = (Byte)tb_loadspeaker.Value; - txb[7] = (Byte)tb_mic.Value; + txb[1] = (Byte)tb_PBvol.Value; + txb[2] = (Byte)tb_CAPvol.Value; + txb[3] = (Byte)cb_announcement.Items.IndexOf(cb_announcement.Text); + txb[4] = (Byte)tb_loadspeaker.Value; + txb[5] = (Byte)tb_mic.Value; + txb[6] = (Byte)0; // unused + txb[7] = (Byte)0; // unused + txb[8] = (Byte)0; // unused + txb[9] = (Byte)0; // unused + + Byte[] bpb = statics.StringToByteArrayUtf8(cb_audioPB.Text); + Byte[] bcap = statics.StringToByteArrayUtf8(cb_audioCAP.Text); + //Byte[] bpb = statics.StringToByteArray(cb_audioPB.Text); + //Byte[] bcap = statics.StringToByteArray(cb_audioCAP.Text); + + for (int i=0; i<100; i++) + { + if (i >= bpb.Length) + txb[i + 10] = 0; + else + txb[i+10] = bpb[i]; + + if (i >= bcap.Length) + txb[i + 110] = 0; + else + txb[i + 110] = bcap[i]; + } Udp.UdpBCsend(txb, GetMyBroadcastIP(), statics.UdpBCport_AppToModem); @@ -1175,7 +1233,7 @@ namespace oscardata TXfilename = open.FileName; TXRealFilename = open.SafeFileName; if (txcommand == statics.BinaryFile) - rtb_TXfile.Text = "Binary file " + TXfilename + " loaded"; + rtb_TXfile.Text = langstr[20] + TXfilename + langstr[21]; else rtb_TXfile.Text = File.ReadAllText(TXfilename); @@ -1336,6 +1394,7 @@ namespace oscardata rb_codec2.Checked = (s != "1"); } catch { } + try { cb_language.Text = ReadString(sr); } catch { } } } catch @@ -1371,6 +1430,7 @@ namespace oscardata sw.WriteLine(tb_loadspeaker.Value.ToString()); sw.WriteLine(tb_mic.Value.ToString()); sw.WriteLine(rb_opus.Checked ? "1" : "0"); + sw.WriteLine(cb_language.Text); } } catch { } @@ -1378,14 +1438,14 @@ namespace oscardata private void bt_shutdown_Click(object sender, EventArgs e) { - DialogResult dr = MessageBox.Show("Do you want to shut down the Modem-Computer ?", "Shut Down Modem", MessageBoxButtons.YesNo); + DialogResult dr = MessageBox.Show(langstr[23], langstr[22], MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) { Byte[] txdata = new byte[1]; txdata[0] = (Byte)statics.Modem_shutdown; Udp.UdpSendCtrl(txdata); - MessageBox.Show("Please wait abt. 1 minute before powering OFF the modem", "Shut Down Modem", MessageBoxButtons.OK); + MessageBox.Show(langstr[24], langstr[22], MessageBoxButtons.OK); } } @@ -1429,14 +1489,14 @@ namespace oscardata recfile.oldblockinfo(d); int failed = d[0] - d[1]; - s = "Received Blocks\n" + + s = langstr[25] + "---------------\n" + "total : " + d[0] + "\n" + - "good : " + d[1] + "\n" + - "failed: " + failed + "\n"; + langstr[26] + d[1] + "\n" + + langstr[27] + failed + "\n"; if(failed > 1) { - s += "\nfile incomplete, ask for retransmission"; + s += langstr[28]; } Form2_showtext sf = new Form2_showtext("Block Info",s); @@ -1445,10 +1505,16 @@ namespace oscardata void setVoiceAudio() { - Byte[] txdata = new byte[5]; + /* + * Format: + * 0 ... statics.SetVoiceMode (25) + * 1 ... voicemode + * 2 ... codec + * 3-102 ... LS device name + * 103-202 ... MIC device name + */ + Byte[] txdata = new byte[203]; txdata[0] = (Byte)statics.SetVoiceMode; - txdata[1] = (Byte)getLSaudioDevice(); - txdata[2] = (Byte)getMICaudioDevice(); Byte opmode = 0; // values see: hsmodem.h _VOICEMODES_ if (cb_switchtoLS.Checked) opmode = 1; @@ -1457,11 +1523,30 @@ namespace oscardata if (cb_digitalVoice.Checked) opmode = 4; if (cb_digitalVoiceRXonly.Checked) opmode = 5; if(opmode == 0) pb_voice.BackgroundImage = null; - txdata[3] = opmode; + txdata[1] = opmode; Byte codec; if (rb_opus.Checked) codec = 0; else codec = 1; - txdata[4] = codec; + txdata[2] = codec; + + Byte[] bpb = statics.StringToByteArrayUtf8(cb_loudspeaker.Text); + Byte[] bcap = statics.StringToByteArrayUtf8(cb_mic.Text); + //Byte[] bpb = statics.StringToByteArray(cb_loudspeaker.Text); + //Byte[] bcap = statics.StringToByteArray(cb_mic.Text); + + for (int i = 0; i < 100; i++) + { + if (i >= bpb.Length) + txdata[i + 3] = 0; + else + txdata[i + 3] = bpb[i]; + + if (i >= bcap.Length) + txdata[i + 103] = 0; + else + txdata[i + 103] = bcap[i]; + } + Udp.UdpSendCtrl(txdata); if(opmode > 0) @@ -1553,5 +1638,235 @@ namespace oscardata { setMICvolume = tb_mic.Value; } + + int language = 0; + void set_language(int lang) + { + language = lang; + + if (language == 0) + { + langstr = langstr_en; + + tabPage_image.Text = "Image"; + label_nextimage.Text = "next image in ..."; + cb_loop.Text = "loop (send all images in folder)"; + bt_rximages.Text = " RX Images"; + button_loadimage.Text = " Load Image"; + label2.Text = "Quality:"; + button_cancelimg.Text = " Cancel"; + button_sendimage.Text = "Send"; + label_rximage.Text = "RX image"; + label_tximage.Text = "TX image"; + tabPage_file.Text = "File"; + button2.Text = "Cancel"; + bt_openrxfile.Text = "Open RX file folder"; + label_rxfile.Text = "RX File"; + label_txfile.Text = "TX File"; + bt_file_send.Text = "SEND"; + bt_sendBinaryFile.Text = "Load Binary File"; + bt_file_html.Text = "Load HTML File"; + bt_file_ascii.Text = " Load ASCII Text File"; + tabPage_audio.Text = "Voice Audio"; + groupBox7.Text = "Codec Selection"; + rb_codec2.Text = "CODEC-2 parametric audio codec. For QPSK. Audio rate: 3200 bps"; + rb_opus.Text = "OPUS rate adaptive codec. For 8APSK. Audio rate: 84% of data rate"; + groupBox6.Text = "Voice Audio Operating Mode"; + cb_digitalVoiceRXonly.Text = "Digital Voice RX: Receiver ---> Codec ---> Loudspeaker"; + cb_digitalVoice.Text = "Digital Voice RX+TX: Microphone ---> Codec ---> Transmitter | Receiver ---> Codec ---> Loudspeaker"; + cb_codecloop.Text = "Codec Loop: Microphone ---> Codec ---> Loudspeaker"; + cb_switchtoLS.Text = "Digital Monitor: Receiver ---> Loudspeaker"; + groupBox5.Text = "Loadspeaker / Microphone / Headset"; + label8.Text = "Volume:"; + label10.Text = "Loadspeaker/Headphone:"; + label11.Text = "Microphone:"; + groupBox4.Text = "Maintenance"; + cb_autostart.Text = "AUTO start/stop HSmodem"; + bt_shutdown.Text = "Shutdown Modem-SBC"; + tb_shutdown.Text = "before switching off the \r\nmodem SBC click here to \r\navoid defective SD-cards.\r\n"; + bt_resetmodem.Text = "Reset RX Modem"; + textBox3.Text = "only uncheck if modem runs on a separate PC"; + groupBox3.Text = "Transceiver Audio"; + label6.Text = "Volume:"; + label5.Text = "Volume:"; + label3.Text = "Audio Playback Device:"; + label4.Text = "Audio Record Device:"; + groupBox2.Text = "Personal Settings"; + cb_stampinfo.Text = "Insert Info into picture"; + textBox5.Text = "every"; + textBox4.Text = "transmissions"; + textBox1.Text = "send announcement before pic/file transfer"; + label1.Text = "Callsign:"; + cb_stampcall.Text = "Insert Callsign into picture"; + tabPage_about.Text = "About"; + label_speed.Text = "Speed [bit/s]:"; + label_fifo.Text = "TX Buffer:"; + bt_blockinfo.Text = "Block Info"; + label_capfifo.Text = "RX Buffer:"; + lb_rxsignal.Text = "RX Signal:"; + lb_rxsync.Text = "RX Sync:"; + + } + + if (language == 1) + { + langstr = langstr_de; + + tabPage_image.Text = "Bilder"; + tabPage_file.Text = "Datei"; + tabPage_audio.Text = "Sprache"; + tabPage_about.Text = "Info"; + label2.Text = "Qualität"; + button_loadimage.Text = "Lade Bild"; + button_sendimage.Text = "Senden"; + button_cancelimg.Text = " Abbruch"; + bt_rximages.Text = "RX Bilder"; + cb_loop.Text = "Endlosschleife: Alle Bilder im Verzeichnis senden"; + label_nextimage.Text = "nächstes Bild in ..."; + label_tximage.Text = "TX Bild"; + label_rximage.Text = "RX Bild"; + label_speed.Text = "Bitrate [bit/s]"; + label_fifo.Text = "TX Puffer"; + label_capfifo.Text = "RX Puffer"; + bt_file_ascii.Text = " Lade ASCII Textdatei"; + bt_file_html.Text = "Lade HTML Datei"; + bt_sendBinaryFile.Text = "Lade Binärdatei"; + bt_file_send.Text = "SENDEN"; + button2.Text = "Abbrechen"; + bt_openrxfile.Text = "Öffne RX Dateien"; + groupBox5.Text = "Lautsprecher / Mikrofon / Kopfhörer"; + label10.Text = "Lautsprecher/Kopfhörer"; + label11.Text = "Mikrofon"; + label9.Text = "Lautst.:"; + label8.Text = "Lautst.:"; + groupBox6.Text = "Sprache / Audio Betriebsart"; + cb_switchtoLS.Text = "Digital Monitor: Empfänger -> Lautsprecher"; + cb_voiceloop.Text = "intere Schleife: Mikrofon -> Lautsprecher"; + cb_codecloop.Text = "Codec Schleife: Mikrofon -> Codec -> Lautsprecher"; + cb_digitalVoiceRXonly.Text = "DV Empfang: Empfänger -> Codec -> Lautsprecher"; + cb_digitalVoice.Text = "DV Transceiver: Mikrofon -> Codec -> Sender | Empfänger -> Codec -> Lautsprecher"; + groupBox7.Text = "Codec Auswahl"; + rb_opus.Text = "OPUS adaptiver Codec. Für 8APSK. Audio-Datenrate 84% der Bitrate"; + rb_codec2.Text = "CODEC-2 parametrischer Audiocodec. Für QPSK. Audiorate: 3200 bit/s"; + groupBox2.Text = "Persönliche Einstellungen"; + label1.Text = "Rufzeichen"; + cb_stampcall.Text = "Füge Rufzeichen ins Bild ein"; + cb_stampinfo.Text = "Füge Infotext ins Bild ein"; + textBox1.Text = "sende Ansagetext vor Daten- oder Bildsendung"; + textBox5.Text = "alle"; + textBox4.Text = "Aussendungen"; + label3.Text = "Audio Wiedergabe"; + label4.Text = "Audio Eingang"; + label5.Text = "Lautst.:"; + label6.Text = "Lautst.:"; + groupBox4.Text = "Wartung"; + textBox3.Text = "Ausschalten wenn hsmodem auf separatem PC läuft"; + tb_shutdown.Text = "Vor dem Ausschalten eines SBC diesen hier herunterfahren"; + } + } + + private void cb_language_SelectedIndexChanged(object sender, EventArgs e) + { + if(cb_language.Text.Contains("Deutsch")) + set_language(1); + else + set_language(0); + } + + String[] langstr; + + String[] langstr_en = new String[]{ + "next image in ", //0 + "transmitting", + "binary file received\r\n", //2 + "transmission time : ", + "transmission speed: ", //4 + "file size : ", + "file name : ", //6 + "file status : not complete, retransmit\r\n\r\n", + "Tuning Window", //8 + "min Level", + "TX image: ", // 10 + ". Sent: ", + "TX file: ", //12 + "Image Files(*.jpg; *.jpeg; *.png; *.gif; *.bmp)|*.jpg; *.jpeg; *.png; *.gif; *.bmp", + " frame lost", //14 + " blocks OK", + "wait for RX", //16 + "Line Speed: ", + " Byte. Missing blocks: ", //18 + " Net Speed:", + "Binary file ", //20 + " loaded", + "Shut Down Modem", //22 + "Do you want to shut down the Modem-Computer ?", + "Please wait abt. 1 minute before powering OFF the modem", //24 + "Received Blocks\n", + "good : ", //26 + "failed: ", + "\nfile incomplete, ask for retransmission", //28 + " sequence OK", + " of ", //30 + "Bad blocks, retransmission required", + "Bad blocks", //32 + }; + + String[] langstr_de = new String[]{ + "nächstes Bild in", //0 + "sende", + "Binärdatei empfangen\r\n", //2 + "Sendezeit : ", + "Ãœbertragungsgeschw: ", //4 + "Dateigröße : ", + "Dateiname : ", //6 + "Dateistatus : nicht komplett \r\n\r\n", + "Tuning Fenster", //8 + "min Pegel", + "TX Bild: ", // 10 + ".Gesendet: ", + "TX Datei: ", //12 + "Bilddateien(*.jpg; *.jpeg; *.png; *.gif; *.bmp)|*.jpg; *.jpeg; *.png; *.gif; *.bmp", + " Frame verloren", //14 + " Blöcken OK", + "warte auf RX", //16 + "Datenrate: ", + " Byte. Fehlende Blöcke: ", //18 + " Netto-Rate:", + "Binärdatei ", //20 + " geladen", + "Modem herunterfahren", //22 + "Wollen sie den Modem Computer herunterfahren?", + "Bitte warten sie 1 Minuten vor dem Ausschalten des Modem Computers", //24 + "empfangene Blöcke\n", + "gut : ", //26 + "defekt: ", + "\nDatei nicht komplett, bitte neu Senden ", //28 + " Sequenz OK", + " von ", //30 + "defekte Blöcke, Datei muss nochmal empfangen werden", + "defekte Blöcke", //32 + }; + + private void cb_autostart_CheckedChanged(object sender, EventArgs e) + { + if (cb_autostart.Checked == false) + { + if (modemrunning) + { + statics.StartHSmodem(false); + Console.WriteLine("Kill Modem"); + modemrunning = false; + } + } + else + { + if (modemrunning == false) + { + modemrunning = statics.StartHSmodem(true); + Console.WriteLine("Start Modem"); + } + } + } } + } diff --git a/oscardata/oscardata/Form1.resx b/oscardata/oscardata/Form1.resx index 6d389e7..4b604ce 100755 --- a/oscardata/oscardata/Form1.resx +++ b/oscardata/oscardata/Form1.resx @@ -137,7 +137,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABw - FwAAAk1TRnQBSQFMAgEBDQEAAdgBAAHYAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + FwAAAk1TRnQBSQFMAgEBDQEAATgBAQE4AQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAAUADAAEBAQABCAYAARAYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -241,17 +241,14 @@ - QO-100 Multimedia High Speed Modem for Linux and Windows + QO-100 Multimedia High Speed Modem (Linux & Windows) -(c) by DJ0ABR, Kurt Moraw, Germany https://dj0abr.de/ -for Amsat-DL: https://amsat-dl.org/ +(c) DJ0ABR, Kurt Moraw, Germany https://dj0abr.de/ +Amsat-DL: https://amsat-dl.org/ Open Source: https://github.com/dj0abr/SSB_HighSpeed_Modem 3rd Party, Credits and Licensing: -BASS audio library: -www.un4seen.com: BASS is free for non-commercial use - DSP Library liquid-DSP: https://liquidsdr.org/ MIT License @@ -266,6 +263,14 @@ GNU General Public License FreeDV: https://github.com/drowe67/codec2 GNU Lesser General Public License v2.1 +Sound Library: libsoundio +https://github.com/andrewrk/libsoundio +MIT License + +Reed Solomon error correction: +https://www.schifra.com/ +License: Schifra User Group 1, GPL V2 + Image from ICON Archive: https://www.iconarchive.com/ Artist: Oxygen Team Iconset: Oxygen Icons (883 icons) @@ -273,7 +278,7 @@ License: GNU Lesser General Public License Artist: Sallee Design (Available for custom work) Iconset: Music Icons (29 icons) -License: CC Attribution 4.0 +License: CC Attribution 4.0 (unchanged, https://creativecommons.org/licenses/by/4.0/) Testing & Manual: DD1US: https://www.dd1us.de/ diff --git a/oscardata/oscardata/Properties/Resources.Designer.cs b/oscardata/oscardata/Properties/Resources.Designer.cs index 09d6a49..ad75e3c 100755 --- a/oscardata/oscardata/Properties/Resources.Designer.cs +++ b/oscardata/oscardata/Properties/Resources.Designer.cs @@ -160,6 +160,16 @@ namespace oscardata.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap hintergrundxcf { + get { + object obj = ResourceManager.GetObject("hintergrundxcf", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -170,26 +180,6 @@ namespace oscardata.Properties { } } - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap image { - get { - object obj = ResourceManager.GetObject("image", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap image1 { - get { - object obj = ResourceManager.GetObject("image1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// diff --git a/oscardata/oscardata/Properties/Resources.resx b/oscardata/oscardata/Properties/Resources.resx index a32a6b4..1db7757 100755 --- a/oscardata/oscardata/Properties/Resources.resx +++ b/oscardata/oscardata/Properties/Resources.resx @@ -121,12 +121,6 @@ Satellite-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - image.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - image1.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - binary.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -208,4 +202,7 @@ redmarker.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + hintergrundxcf.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/oscardata/oscardata/Properties/hintergrundxcf.png b/oscardata/oscardata/Properties/hintergrundxcf.png new file mode 100644 index 0000000..17842ad Binary files /dev/null and b/oscardata/oscardata/Properties/hintergrundxcf.png differ diff --git a/oscardata/oscardata/bin/Debug/oscardata.exe b/oscardata/oscardata/bin/Debug/oscardata.exe deleted file mode 100755 index c747714..0000000 Binary files a/oscardata/oscardata/bin/Debug/oscardata.exe and /dev/null differ diff --git a/oscardata/oscardata/bin/Debug/oscardata.exe.config b/oscardata/oscardata/bin/Debug/oscardata.exe.config deleted file mode 100755 index e743be0..0000000 --- a/oscardata/oscardata/bin/Debug/oscardata.exe.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/oscardata/oscardata/bin/Debug/oscardata.pdb b/oscardata/oscardata/bin/Debug/oscardata.pdb deleted file mode 100755 index 58af86c..0000000 Binary files a/oscardata/oscardata/bin/Debug/oscardata.pdb and /dev/null differ diff --git a/oscardata/oscardata/bin/Release/oscardata.exe b/oscardata/oscardata/bin/Release/oscardata.exe index 80be768..69e11f1 100755 Binary files a/oscardata/oscardata/bin/Release/oscardata.exe and b/oscardata/oscardata/bin/Release/oscardata.exe differ diff --git a/oscardata/oscardata/bin/Release/oscardata.exe.config b/oscardata/oscardata/bin/Release/oscardata.exe.config deleted file mode 100755 index e743be0..0000000 --- a/oscardata/oscardata/bin/Release/oscardata.exe.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/oscardata/oscardata/bin/Release/oscardata.pdb b/oscardata/oscardata/bin/Release/oscardata.pdb deleted file mode 100755 index 9c7efec..0000000 Binary files a/oscardata/oscardata/bin/Release/oscardata.pdb and /dev/null differ diff --git a/oscardata/oscardata/config.cs b/oscardata/oscardata/config.cs index 344a9ee..0ea8f80 100755 --- a/oscardata/oscardata/config.cs +++ b/oscardata/oscardata/config.cs @@ -149,6 +149,12 @@ namespace oscardata return enc.GetBytes(str); } + public static byte[] StringToByteArrayUtf8(string str) + { + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); + return enc.GetBytes(str); + } + public static string ByteArrayToString(byte[] arr, int offset = 0) { Byte[] ba = new byte[arr.Length]; @@ -161,6 +167,23 @@ namespace oscardata Array.Copy(ba, ban, dst); System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + + return enc.GetString(ban); + } + + public static string ByteArrayToStringUtf8(byte[] arr, int offset = 0) + { + Byte[] ba = new byte[arr.Length]; + int dst = 0; + for (int i = offset; i < arr.Length; i++) + { + if (arr[i] != 0) ba[dst++] = arr[i]; + } + Byte[] ban = new byte[dst]; + Array.Copy(ba, ban, dst); + + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); + return enc.GetString(ban); } @@ -315,36 +338,40 @@ namespace oscardata } static Process cmd = null; - public static bool StartHSmodem() + public static bool StartHSmodem(bool start = true) { // kill old processes already running killall("hsmodem"); killall("hsmodem.exe"); - // starte Prozesse - try - { - if (ostype == 0) - { - if (!File.Exists("hsmodem.exe")) return false; - cmd = new Process(); - cmd.StartInfo.FileName = "hsmodem.exe"; - } - else - { - if (!File.Exists("hsmodem")) return false; - cmd = new Process(); - cmd.StartInfo.FileName = "hsmodem"; - } - if (cmd != null) + if (start == true) + { + // starte Prozesse + try { - cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;// .Hidden; - cmd.StartInfo.Arguments = ""; - cmd.Start(); - Console.WriteLine("hsmodem started"); + if (ostype == 0) + { + if (!File.Exists("hsmodem.exe")) return false; + cmd = new Process(); + cmd.StartInfo.FileName = "hsmodem.exe"; + } + else + { + if (!File.Exists("hsmodem")) return false; + cmd = new Process(); + cmd.StartInfo.FileName = "hsmodem"; + } + + if (cmd != null) + { + cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;// .Hidden; + cmd.StartInfo.Arguments = ""; + cmd.Start(); + Console.WriteLine("hsmodem started"); + } } + catch { return false; } } - catch { return false; } return true; } diff --git a/oscardata/oscardata/oscardata.csproj b/oscardata/oscardata/oscardata.csproj index 2fcce72..febefe6 100755 --- a/oscardata/oscardata/oscardata.csproj +++ b/oscardata/oscardata/oscardata.csproj @@ -139,6 +139,7 @@ + diff --git a/oscardata/oscardata/receivefile.cs b/oscardata/oscardata/receivefile.cs index 6fa0c62..8429080 100755 --- a/oscardata/oscardata/receivefile.cs +++ b/oscardata/oscardata/receivefile.cs @@ -81,7 +81,15 @@ namespace oscardata bool autoRXnum = false; String blockFilename = ""; - public bool receive(Byte []rxdp) + // 1 ... file OK + // 0 ... continue receiving + // -1 ... invalid header + // -2 ... first frame invalid + // -3 ... invalid data in cont frame + // -4 ... invalid data in last frame + // -5 ... file ends, but bad blocks + + public int receive(Byte []rxdp) { // read frame header if(!getFrameHeader(rxdp)) @@ -89,17 +97,18 @@ namespace oscardata // invalid situation blockidx = 0; receiving = false; - return false; + return -1; } // receive first frame of a transmission if (minfo == statics.FirstFrame || minfo == statics.SingleFrame) { + receiving = false; starttime = DateTime.UtcNow; rxbytes = 0; filesize = 0; filename = ""; - if (!StartFileRX()) return false; // invalid file + if (!StartFileRX()) return -2; // invalid file } if (receiving && minfo != statics.FirstFrame) @@ -114,7 +123,7 @@ namespace oscardata // invalid situation blockidx = 0; receiving = false; - return false; + return -3; } } @@ -128,12 +137,17 @@ namespace oscardata // invalid situation blockidx = 0; receiving = false; - return false; + return -4; } // the last block was received ok // save file if all blocks valid - SaveFile(); + bool fileisok = SaveFile(); + if(fileisok == false) + { + // file not complete, do not to unzip + return -5; + } blockidx = 0; receiving = false; @@ -142,7 +156,7 @@ namespace oscardata // these file type must be unzipped handleZIPfiles(); receiving = false; - return true; + return 1; } } @@ -150,10 +164,10 @@ namespace oscardata { // build bitmap from received data pbmp = buildBitmap(); - return true; + return 1; } - return false; + return 0; } bool getFrameHeader(Byte[] rxd) @@ -279,6 +293,26 @@ namespace oscardata result[1] = ok; } + public String missingBlockString() + { + String s = ""; + bool f = true; + for (int i = 0; i <= lastblockidx; i++) + { + if (!lastblockvalid[i]) + { + if (!f) + s += ", "; + else + f = false; + + s += i.ToString(); + } + } + + return s; + } + void saveBlocks() { try @@ -336,7 +370,7 @@ namespace oscardata { if (!receiving) { - Console.WriteLine("next/last block: not receiving, first block missing?"); + //Console.WriteLine("next/last block: not receiving, first block missing?"); return false; } diff --git a/oscardata/oscardata/udp.cs b/oscardata/oscardata/udp.cs index b68dab7..d505c4e 100755 --- a/oscardata/oscardata/udp.cs +++ b/oscardata/oscardata/udp.cs @@ -101,7 +101,8 @@ namespace oscardata statics.initAudioStatus = b[0]; statics.initVoiceStatus = b[1]; - String s = statics.ByteArrayToString(b,2); + //String s = statics.ByteArrayToString(b,2); + String s = statics.ByteArrayToStringUtf8(b, 2); String[] sa1 = s.Split(new char[] { '^' }); statics.AudioPBdevs = sa1[0].Split(new char[] { '~' }); statics.AudioCAPdevs = sa1[1].Split(new char[] { '~' });