diff options
-rw-r--r-- | asndfile.gpr | 20 | ||||
-rw-r--r-- | example.gpr | 27 | ||||
-rw-r--r-- | example/read_example.adb | 4 | ||||
-rw-r--r-- | proj/common.gpr | 102 | ||||
-rw-r--r-- | readme.md | 84 | ||||
-rw-r--r-- | readme.txt | 73 | ||||
-rw-r--r-- | src/libsndfile-commands.adb | 77 | ||||
-rw-r--r-- | src/libsndfile-virtual.adb | 12 | ||||
-rw-r--r-- | src/libsndfile.adb | 17 | ||||
-rw-r--r-- | src/libsndfile.ads | 7 |
10 files changed, 270 insertions, 153 deletions
diff --git a/asndfile.gpr b/asndfile.gpr index 07c41c5..52a80de 100644 --- a/asndfile.gpr +++ b/asndfile.gpr @@ -1,22 +1,24 @@ +with + + "proj/common"; + + library project Asndfile is for Languages use ("Ada", "C"); - - for Source_Dirs use ("src"); - for Object_Dir use "obj"; - for Library_Dir use "lib"; + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Library_Dir use "lib"; for Library_Name use "asndfile"; for Library_Kind use "dynamic"; - - package Compiler is - for Default_Switches ("Ada") use ("-gnaty4aAbcefhiklM100nprt"); - for Default_Switches ("C") use ("-Wall", "-Wextra"); - end Compiler; + package Builder renames Common.Builder; + package Compiler renames Common.Compiler; + package Binder renames Common.Binder; end Asndfile; diff --git a/example.gpr b/example.gpr index 9f8479e..e799be2 100644 --- a/example.gpr +++ b/example.gpr @@ -1,6 +1,9 @@ -with "asndfile"; +with + + "asndfile", + "proj/common"; project Example is @@ -8,23 +11,29 @@ project Example is for languages use ("Ada"); - for Source_Dirs use ("example"); for Object_Dir use "obj"; for Exec_Dir use "bin"; - for Main use ("file_info_example.adb", "read_example.adb", "virtual_io_example.adb"); + for Main use + ("file_info_example.adb", + "read_example.adb", + "virtual_io_example.adb"); package Builder is - for Executable("file_info_example.adb") use "info_example"; - for Executable("read_example.adb") use "read_example"; + for Executable("file_info_example.adb") use "info_example"; + for Executable("read_example.adb") use "read_example"; for Executable("virtual_io_example.adb") use "virtual_example"; - end Builder; + for Default_Switches ("Ada") use + Common.Builder'Default_Switches ("Ada"); + for Global_Compilation_Switches ("Ada") use + Common.Builder'Global_Compilation_Switches ("Ada"); + end Builder; - package Compiler is - for Default_Switches("Ada") use ("-gnaty4aAbcefhiklM100nprt"); - end Compiler; + package Compiler renames Common.Compiler; + package Binder renames Common.Binder; + package Linker renames Common.Linker; end Example; diff --git a/example/read_example.adb b/example/read_example.adb index 719e7ec..531ed5f 100644 --- a/example/read_example.adb +++ b/example/read_example.adb @@ -52,8 +52,8 @@ begin TIO.New_Line; declare - Channel_Count : Natural := My_Info.Channels; - Test_Frames : Libsndfile.Count_Type := 5; + Channel_Count : constant Natural := My_Info.Channels; + Test_Frames : constant Libsndfile.Count_Type := 5; My_Shorts : Libsndfile.Short_Data (1 .. Natural (Test_Frames) * Channel_Count); My_Integers : Libsndfile.Integer_Data (1 .. Natural (Test_Frames) * Channel_Count); diff --git a/proj/common.gpr b/proj/common.gpr new file mode 100644 index 0000000..a251d70 --- /dev/null +++ b/proj/common.gpr @@ -0,0 +1,102 @@ + + +abstract project Common is + + + type Build_Kind is ("release", "debug"); + + Ver : Build_Kind := external ("build", "release"); + + + package Builder is + for Default_Switches ("Ada") use ("-j4", "-m"); + for Global_Compilation_Switches ("Ada") use ("-shared"); + + case Ver is + + when "release" => + null; + + when "debug" => + for Default_Switches ("Ada") use Builder'Default_Switches ("Ada") & "-g"; + + end case; + end Builder; + + + Ada_Common := + ("-gnaty" + & "4" -- indentation + & "a" -- attribute casing + & "A" -- array attribute indices + & "b" -- blanks at end of lines + & "c" -- two space comments + & "e" -- end/exit labels + & "f" -- no form feeds or vertical tabs + & "h" -- no horizontal tabs + & "i" -- if/then layout + & "k" -- keyword casing + & "l" -- reference manual layout + & "M100" -- max line length + & "n" -- package Standard casing + & "p" -- pragma casing + & "r" -- identifier casing + & "t", -- token separation + "-gnatw" + & "a" -- various warning modes + & "F" -- don't check for unreferenced formal parameters + & "J" -- don't check for obsolescent feature use + & "U"); -- don't check for unused entities + + C_Common := + ("-Wall", + "-Werror", + "-Wextra", + "-Wpedantic"); + + package Compiler is + case Ver is + + when "release" => + for Default_Switches ("Ada") use Ada_Common & "-O3" & "-gnatn"; + for Default_Switches ("C") use C_Common & "-O3"; + + when "debug" => + for Default_Switches ("Ada") use Ada_Common & "-O0" & "-gnata" & "-gnato" & "-g"; + for Default_Switches ("C") use C_Common & "-O0"; + + end case; + end Compiler; + + + package Binder is + for Default_Switches ("Ada") use ("-shared"); + + case Ver is + + when "release" => + null; + + when "debug" => + for Default_Switches ("Ada") use Binder'Default_Switches ("Ada") & "-Es"; + + end case; + end Binder; + + + package Linker is + case Ver is + + when "release" => + null; + + when "debug" => + for Default_Switches ("Ada") use ("-g"); + + end case; + end Linker; + + +end Common; + + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..174280c --- /dev/null +++ b/readme.md @@ -0,0 +1,84 @@ + +## libsndfile Binding for the Ada Programming Language + +This is a thick binding of [libsndfile](https://libsndfile.github.io/libsndfile/) +so effort has been made to get rid of all C-isms and C-specific types wherever +possible. In particular: + +<ul> + <li>All error codes have been converted to exceptions</li> + <li>Void pointers are completely absent</li> + <li>The command API has been mapped to a more ordinary collection of + subprograms instead of the single function it is in C</li> +</ul> + +The package hierarchy is as follows: + +<ul> + <li>Libsndfile (Everything that isn't virtual IO or the command API) + <ul> + <li>Libsndfile.Commands (The command API datatypes and subprograms)</li> + <li>Libsndfile.Virtual (The virtual IO interface)</li> + </ul> + </li> +</ul> + +A few short example programs are available in the `example` subdirectory. + +Please note that at the moment this binding is incomplete, as the RIFF chunk +API is not bound. If anyone has a pressing need for it let me know. + +Finally, there appears to be a subtle bug in the virtual IO that causes the +frame count to be one lower than it should be. I am currently unsure of the +exact cause. Since the behaviour is the same regardless of whether using the +virtual IO in C or in Ada, the likely culprit is in the library itself. + + + +#### Dependencies + +Build time: +<ul> + <li>gcc</li> + <li>GNAT</li> + <li>GPRbuild</li> + <li>libsndfile</li> +</ul> + +Run time: +<ul> + <li>libsndfile</li> +</ul> + + + +#### Building and Installation + +This repository is written to use the GNAT Project Manager build tools. To +build, use the following command + +`gprbuild asndfile.gpr` + +There is a single build switch of `-Xbuild` which can have a value of `release` +(the default) or `debug`. + +To install the binding, use + +`gprinstall -p -m asndfile.gpr` + +The other gpr file `example.gpr` can be used to build the short example +programs provided. + +For further information on the build tools, consult the +[GPRbuild docs](https://docs.adacore.com/gprbuild-docs/html/gprbuild_ug.html). + + + +#### Credits and Licensing + +This binding and the Ada test/example programs were written by Jedidiah Barber. + +All code of this binding and example programs is released into the public +domain. Consult `unlicense.txt` for further information. + + diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 92d267d..0000000 --- a/readme.txt +++ /dev/null @@ -1,73 +0,0 @@ - - -libsndfile Binding for the Ada Programming Language -=================================================== - - -Overview --------- - -This is a thick binding, so effort has been made to get rid of all C-isms and -C-specific types wherever possible. In particular: - - * All error codes have been converted to exceptions - * Void pointers are completely absent - * The command API has been mapped to a more ordinary collection of subprograms - instead of the single function it is in C - -The package hierarchy is as follows: - - * Libsndfile: Everything that isn't virtual IO or the command API - * Libsndfile.Commands: The command API datatypes and subprograms - * Libsndfile.Virtual: The virtual IO interface - -A few short example programs are available in /example/. - -Please note that at the moment this binding is incomplete, as the RIFF chunk -API is not bound. If anyone has a pressing need for it let me know. - -Finally, there appears to be a subtle bug in the virtual IO that causes the -frame count to be one lower than it should be. I am currently unsure of the -exact cause. Since the behaviour is the same regardless of whether using the -virtual IO in C or in Ada, the likely culprit is in the library itself. - - -Dependencies ------------- - -An Ada 2012 compiler and standard library (build) -A C compiler and standard library (build) -gprbuild (build) -libsndfile (run) - - -Build Instructions ------------------- - -Ensure that all dependencies are installed, including any developer or header -packages for libsndfile. Then the following commands will build and install the -binding: - - gprbuild libsndfile.gpr - gprinstall -p -m libsndfile.gpr - -The other gpr file, example.gpr, can be used to build the few short example and -test programs provided. - - -Further Information -------------------- - -C API of libsndfile: -https://libsndfile.github.io/libsndfile/api.html - - -Credits and Legal ------------------ - -This binding and the Ada test/example programs were written by Jedidiah Barber. - -All code of this binding and example programs is released into the public -domain. Consult unlicense.txt for further information. - - diff --git a/src/libsndfile-commands.adb b/src/libsndfile-commands.adb index 1939cd7..5338a7b 100644 --- a/src/libsndfile-commands.adb +++ b/src/libsndfile-commands.adb @@ -9,9 +9,8 @@ pragma Ada_2012; with - Ada.Assertions, Ada.Strings.Fixed, - Interfaces.C.Strings; + Interfaces.C; use type @@ -302,7 +301,7 @@ package body Libsndfile.Commands is (Info : in Format_Info) return Major_Format is - Raw : Interfaces.Unsigned_32 := + Raw : constant Interfaces.Unsigned_32 := Interfaces.Unsigned_32 (Info.C_Data.My_Format) and sf_format_typemask; begin return To_Major (Interfaces.C.int (Raw)); @@ -312,7 +311,7 @@ package body Libsndfile.Commands is (Info : in Format_Info) return Minor_Format is - Raw : Interfaces.Unsigned_32 := + Raw : constant Interfaces.Unsigned_32 := Interfaces.Unsigned_32 (Info.C_Data.My_Format) and sf_format_submask; begin return To_Minor (Interfaces.C.int (Raw)); @@ -322,7 +321,7 @@ package body Libsndfile.Commands is (Info : in Format_Info) return Endianness is - Raw : Interfaces.Unsigned_32 := + Raw : constant Interfaces.Unsigned_32 := Interfaces.Unsigned_32 (Info.C_Data.My_Format) and sf_format_endmask; begin return To_Endian (Interfaces.C.int (Raw)); @@ -496,7 +495,6 @@ package body Libsndfile.Commands is Result : Long_Float_Array (1 .. Natural (File.Chans)); Code : Interfaces.C.int; begin - Ada.Assertions.Assert (Long_Float'Size = Interfaces.C.double'Size); Code := sf_command (File.Ptr, sfc_calc_max_all_channels, @@ -517,7 +515,6 @@ package body Libsndfile.Commands is Result : Long_Float_Array (1 .. Natural (File.Chans)); Code : Interfaces.C.int; begin - Ada.Assertions.Assert (Long_Float'Size = Interfaces.C.double'Size); Code := sf_command (File.Ptr, sfc_calc_norm_max_all_channels, @@ -577,26 +574,26 @@ package body Libsndfile.Commands is (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_set_norm_float, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end Set_Normed_Float; procedure Set_Normed_Double (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_set_norm_double, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end Set_Normed_Double; function Get_Normed_Float @@ -643,34 +640,34 @@ package body Libsndfile.Commands is (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_set_scale_float_int_read, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end Set_Scale_Float_Integer_Read; procedure Set_Scale_Integer_Float_Write (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_set_scale_int_float_write, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end Set_Scale_Integer_Float_Write; function Get_Simple_Format_Count return Natural is - Result, Code : Interfaces.C.int; + Result, Ignore : Interfaces.C.int; begin - Code := sf_command + Ignore := sf_command (Null_Pointer, sfc_get_simple_format_count, Storage.To_Integer (Result'Address), @@ -743,9 +740,9 @@ package body Libsndfile.Commands is function Get_Format_Major_Count return Natural is - Result, Code : Interfaces.C.int; + Result, Ignore : Interfaces.C.int; begin - Code := sf_command + Ignore := sf_command (Null_Pointer, sfc_get_format_major_count, Storage.To_Integer (Result'Address), @@ -778,9 +775,9 @@ package body Libsndfile.Commands is function Get_Format_Subtype_Count return Natural is - Result, Code : Interfaces.C.int; + Result, Ignore : Interfaces.C.int; begin - Code := sf_command + Ignore := sf_command (Null_Pointer, sfc_get_format_subtype_count, Storage.To_Integer (Result'Address), @@ -814,38 +811,38 @@ package body Libsndfile.Commands is (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_set_add_peak_chunk, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end Set_Add_Peak_Chunk; procedure Update_Header_Now (File : in Sound_File) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_update_header_now, Null_Pointer, 0); + begin + null; end Update_Header_Now; procedure Set_Update_Header_Auto (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_set_update_header_auto, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end Set_Update_Header_Auto; procedure File_Truncate @@ -876,13 +873,13 @@ package body Libsndfile.Commands is (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_set_clipping, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end Set_Clipping; function Get_Clipping @@ -1441,13 +1438,13 @@ package body Libsndfile.Commands is (File : in Sound_File; Value : in Boolean) is - Code : Interfaces.C.int; - begin - Code := sf_command + Ignore : Interfaces.C.int := sf_command (File.Ptr, sfc_rf64_auto_downgrade, Null_Pointer, (if Value then sf_true else sf_false)); + begin + null; end RF64_Auto_Downgrade; function Get_Original_Samplerate diff --git a/src/libsndfile-virtual.adb b/src/libsndfile-virtual.adb index 8a54837..1aae30b 100644 --- a/src/libsndfile-virtual.adb +++ b/src/libsndfile-virtual.adb @@ -47,7 +47,7 @@ package body Libsndfile.Virtual is (Data : in Storage.Integer_Address) return Interfaces.Integer_64 is - Virtual : Virt_Conversions.Object_Pointer := + Virtual : constant Virt_Conversions.Object_Pointer := Virt_Conversions.To_Pointer (Storage.To_Address (Data)); begin return Interfaces.Integer_64 (Virtual.My_Length.all); @@ -60,7 +60,7 @@ package body Libsndfile.Virtual is Data : in Storage.Integer_Address) return Interfaces.Integer_64 is - Virtual : Virt_Conversions.Object_Pointer := + Virtual : constant Virt_Conversions.Object_Pointer := Virt_Conversions.To_Pointer (Storage.To_Address (Data)); My_Whence : Seek_From; begin @@ -83,7 +83,7 @@ package body Libsndfile.Virtual is Data : in Storage.Integer_Address) return Interfaces.Integer_64 is - Virtual : Virt_Conversions.Object_Pointer := + Virtual : constant Virt_Conversions.Object_Pointer := Virt_Conversions.To_Pointer (Storage.To_Address (Data)); Buffer : Raw_Data (1 .. Integer (Count)); for Buffer'Address use Storage.To_Address (Ptr); @@ -99,7 +99,7 @@ package body Libsndfile.Virtual is Data : in Storage.Integer_Address) return Interfaces.Integer_64 is - Virtual : Virt_Conversions.Object_Pointer := + Virtual : constant Virt_Conversions.Object_Pointer := Virt_Conversions.To_Pointer (Storage.To_Address (Data)); Buffer : Raw_Data (1 .. Integer (Count)); for Buffer'Address use Storage.To_Address (Ptr); @@ -113,7 +113,7 @@ package body Libsndfile.Virtual is (Data : in Storage.Integer_Address) return Interfaces.Integer_64 is - Virtual : Virt_Conversions.Object_Pointer := + Virtual : constant Virt_Conversions.Object_Pointer := Virt_Conversions.To_Pointer (Storage.To_Address (Data)); begin return Interfaces.Integer_64 (Virtual.My_Tell.all); @@ -136,7 +136,7 @@ package body Libsndfile.Virtual is Write : in Write_Function; Tell : in Tell_Function) is - Mode_Int : Interfaces.C.int := (case Mode is + Mode_Int : constant Interfaces.C.int := (case Mode is when Read_Only => sfm_read, when Write_Only => sfm_write, when Read_Write => sfm_rdwr); diff --git a/src/libsndfile.adb b/src/libsndfile.adb index 7cc9837..80f1d96 100644 --- a/src/libsndfile.adb +++ b/src/libsndfile.adb @@ -9,7 +9,6 @@ pragma Ada_2012; with - Ada.Assertions, Interfaces.C.Strings; use type @@ -800,7 +799,7 @@ package body Libsndfile is Mode : in File_Mode; Info : in out File_Info'Class) is - Mode_Int : Interfaces.C.int := (case Mode is + Mode_Int : constant Interfaces.C.int := (case Mode is when Read_Only => sfm_read, when Write_Only => sfm_write, when Read_Write => sfm_rdwr); @@ -821,7 +820,7 @@ package body Libsndfile is (Info : in File_Info) return Boolean is - Result : Interfaces.C.int := asf_format_check (Info.Data); + Result : constant Interfaces.C.int := asf_format_check (Info.Data); begin if Result = sf_true then return True; @@ -893,7 +892,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Short_Integer'Size = Interfaces.C.short'Size); return Count_Type (asf_readf_short (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Read_Short; @@ -907,7 +905,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Integer'Size = Interfaces.C.int'Size); return Count_Type (asf_readf_int (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Read_Integer; @@ -921,7 +918,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Float'Size = Interfaces.C.C_float'Size); return Count_Type (asf_readf_float (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Read_Float; @@ -935,7 +931,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Long_Float'Size = Interfaces.C.double'Size); return Count_Type (asf_readf_double (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Read_Double; @@ -949,7 +944,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Short_Integer'Size = Interfaces.C.short'Size); return Count_Type (asf_writef_short (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Write_Short; @@ -963,7 +957,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Integer'Size = Interfaces.C.int'Size); return Count_Type (asf_writef_int (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Write_Integer; @@ -977,7 +970,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Float'Size = Interfaces.C.C_float'Size); return Count_Type (asf_writef_float (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Write_Float; @@ -991,7 +983,6 @@ package body Libsndfile is for Buffer'Address use Data'Address; pragma Import (Ada, Buffer); begin - Ada.Assertions.Assert (Long_Float'Size = Interfaces.C.double'Size); return Count_Type (asf_writef_double (File.Ptr, Buffer, Interfaces.Integer_64 (Frames))); end Write_Double; @@ -1001,7 +992,6 @@ package body Libsndfile is Bytes : in Count_Type) return Count_Type is begin - Ada.Assertions.Assert (Character'Size = 8); return Count_Type (asf_read_raw (File.Ptr, Storage.To_Integer (Data'Address), @@ -1014,7 +1004,6 @@ package body Libsndfile is Bytes : in Count_Type) return Count_Type is begin - Ada.Assertions.Assert (Character'Size = 8); return Count_Type (asf_write_raw (File.Ptr, Storage.To_Integer (Data'Address), @@ -1084,7 +1073,7 @@ package body Libsndfile is (File : in Sound_File) return Natural is - Result : Interfaces.C.int := sf_current_byterate (File.Ptr); + Result : constant Interfaces.C.int := sf_current_byterate (File.Ptr); begin if Result >= 0 then return Natural (Result); diff --git a/src/libsndfile.ads b/src/libsndfile.ads index 65ffeac..f996f9d 100644 --- a/src/libsndfile.ads +++ b/src/libsndfile.ads @@ -363,6 +363,13 @@ private (c_pointer_size * Interfaces.C.CHAR_BIT = Storage.Integer_Address'Size, "Size of C void pointers and size of Ada address values do not match"); + -- More things that shouldn't fail unless something really weird happens + pragma Assert (Short_Integer'Size = Interfaces.C.short'Size); + pragma Assert (Integer'Size = Interfaces.C.int'Size); + pragma Assert (Float'Size = Interfaces.C.C_float'Size); + pragma Assert (Long_Float'Size = Interfaces.C.double'Size); + pragma Assert (Character'Size = Interfaces.C.CHAR_BIT); + pragma Inline (Is_Open); pragma Inline (Write_Sync); |