diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6f9e545..32daed6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,24 +1,26 @@
 name: CI
 
-on: [push]
+on:
+  pull_request:
+  push:
+    branches:
+      - main
 
 jobs:
+  cancel_previous_run:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cancel Previous Runs
+        uses: styfle/cancel-workflow-action@0.4.0
+        with:
+          access_token: ${{ github.token }}
+
   build:
     runs-on: ${{ matrix.os }}
     strategy:
+      fail-fast: false
       matrix:
         os: [ubuntu-latest, macos-latest]
     steps:
-    - uses: actions/checkout@v1
-    - name: Setup OCaml
-      uses: avsm/setup-ocaml@v1.0
-    - name: Install depext module
-      run: opam install -y depext
-    - name: Pin locally
-      run: opam pin -y add --no-action .
-    - name: Install locally
-      run: opam depext -y -i shine
-    - name: Build locally
-      run: eval $(opam env) && dune build
-    - name: Run tests locally
-      run: eval $(opam env) && dune runtest
+    - name: Build and test module
+      uses: savonet/build-and-test-ocaml-module@main
diff --git a/.ocamlformat b/.ocamlformat
index 533d804..ff63c58 100644
--- a/.ocamlformat
+++ b/.ocamlformat
@@ -1,3 +1,4 @@
+version=0.19.0
 profile = conventional
 break-separators = after
 space-around-lists = false
diff --git a/CHANGES b/CHANGES
index 65d4e83..a6e2441 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+0.2.3 (2022-04-12)
+=====
+* Fix endianess detection.
+
 0.2.2 (2021-10-31) 🎃
 =====
 * Switch to dune 2
diff --git a/README.md b/README.md
index 602ca0b..253410c 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Prerequisites:
 
 - ocaml
 
-- lame
+- libshine
 
 - findlib
 
diff --git a/dune-project b/dune-project
index c4687e1..ca56924 100644
--- a/dune-project
+++ b/dune-project
@@ -1,5 +1,5 @@
-(lang dune 2.7)
-(version 0.2.2)
+(lang dune 2.8)
+(version 0.2.3)
 (name shine)
 (source (github savonet/ocaml-shine))
 (license GPL-2.0)
@@ -7,6 +7,7 @@
 (maintainers "The Savonet Team <savonet-users@lists.sourceforge.net>")
 
 (generate_opam_files true)
+(use_standard_c_and_cxx_flags false)
 
 (package
  (name shine)
diff --git a/examples/encode.ml b/examples/encode.ml
index 930d959..1aa4ba0 100644
--- a/examples/encode.ml
+++ b/examples/encode.ml
@@ -3,10 +3,16 @@ let dst = ref ""
 let buflen = ref 1024
 
 let input_string chan len =
-  let ans = Bytes.create len in
-  (* TODO: check length *)
-  ignore (input chan ans 0 len);
-  Bytes.to_string ans
+  let ans = Buffer.create len in
+  let buf = Bytes.create len in
+  let rec f rem =
+    if 0 < rem then (
+      let ret = input chan buf 0 rem in
+      Buffer.add_subbytes ans buf 0 ret;
+      f (rem - ret))
+  in
+  f len;
+  Buffer.contents ans
 
 let input_int chan =
   let buf = input_string chan 4 in
@@ -37,7 +43,7 @@ let _ =
     usage;
   if !src = "" || !dst = "" then (
     Printf.printf "%s\n" usage;
-    exit 1 );
+    exit 1);
   let ic = open_in_bin !src in
   (* TODO: improve! *)
   if input_string ic 4 <> "RIFF" then invalid_arg "No RIFF tag";
@@ -64,7 +70,14 @@ let _ =
   Printf.printf
     "Encoding to: MP3 %d channels, %d Hz, bitrate: %d\nPlease wait...\n%!"
     channels infreq !bitrate;
-  if input_string ic 4 <> "data" then invalid_arg "No data tag";
+  let rec f () =
+    let tag = input_string ic 4 in
+    let len = input_int ic in
+    if tag <> "data" then (
+      ignore (input_string ic len);
+      f ())
+  in
+  f ();
   (* This ensures the actual audio data will start on a new page, as per
    * spec. *)
   let buflen = 2 * channels * Shine.samples_per_pass enc in
diff --git a/shine.opam b/shine.opam
index 47de865..75d3407 100644
--- a/shine.opam
+++ b/shine.opam
@@ -1,6 +1,6 @@
 # This file is generated by dune, edit dune-project instead
 opam-version: "2.0"
-version: "0.2.2"
+version: "0.2.3"
 synopsis: "Fixed-point MP3 encoder"
 description:
   "shine is a super fast mp3 encoding library implemented in fixed-point arithmetic."
@@ -11,7 +11,7 @@ homepage: "https://github.com/savonet/ocaml-shine"
 bug-reports: "https://github.com/savonet/ocaml-shine/issues"
 depends: [
   "ocaml" {>= "4.03.0"}
-  "dune" {>= "2.7"}
+  "dune" {>= "2.8"}
   "conf-shine"
   "dune-configurator"
   "odoc" {with-doc}
diff --git a/src/config/discover.ml b/src/config/discover.ml
index 6e2183f..2a95417 100644
--- a/src/config/discover.ml
+++ b/src/config/discover.ml
@@ -1,7 +1,12 @@
 module C = Configurator.V1
 
+external is_big_endian : unit -> bool = "ocaml_shine_is_big_endian"
+
 let () =
   C.main ~name:"shine-pkg-config" (fun c ->
+      C.C_define.gen_header_file c ~fname:"config.h"
+        [("IS_BIGENDIAN", Switch (is_big_endian ()))];
+
       let default : C.Pkg_config.package_conf =
         { libs = ["-lshine"]; cflags = [] }
       in
@@ -11,7 +16,7 @@ let () =
           | Some pc -> (
               match C.Pkg_config.query pc ~package:"shine" with
                 | None -> default
-                | Some deps -> deps )
+                | Some deps -> deps)
       in
 
       C.Flags.write_sexp "c_flags.sexp" conf.cflags;
diff --git a/src/config/dune b/src/config/dune
index 21a5f9a..5c0a90b 100644
--- a/src/config/dune
+++ b/src/config/dune
@@ -1,3 +1,6 @@
 (executable
  (name discover)
+ (foreign_stubs
+  (language c)
+  (names endianess))
  (libraries dune.configurator))
diff --git a/src/config/endianess.c b/src/config/endianess.c
new file mode 100644
index 0000000..4839e2f
--- /dev/null
+++ b/src/config/endianess.c
@@ -0,0 +1,20 @@
+#include <caml/memory.h>
+#include <stdint.h>
+
+enum
+{
+    OCAML_SHINE_LITTLE_ENDIAN = 0x0100,
+    OCAML_SHINE_BIG_ENDIAN = 0x0001,
+};
+
+static const union { unsigned char bytes[2]; uint16_t value; } host_order =
+    { { 0, 1 } };
+
+CAMLprim value ocaml_shine_is_big_endian(value unit) {
+  CAMLparam0();
+
+  if (host_order.value == OCAML_SHINE_BIG_ENDIAN)
+    CAMLreturn(Val_bool(1));
+
+  CAMLreturn(Val_bool(0));
+}
diff --git a/src/dune b/src/dune
index 6f3c240..e98b3af 100644
--- a/src/dune
+++ b/src/dune
@@ -4,6 +4,7 @@
  (synopsis "Fixed-point MP3 encoder.")
  (foreign_stubs
   (language c)
+  (extra_deps config.h)
   (names shine_stubs)
   (flags
    (:include c_flags.sexp)))
@@ -11,7 +12,7 @@
   (:include c_library_flags.sexp)))
 
 (rule
- (targets c_flags.sexp c_library_flags.sexp)
+ (targets c_flags.sexp c_library_flags.sexp config.h)
  (deps
   (:discover config/discover.exe))
  (action
diff --git a/src/shine_stubs.c b/src/shine_stubs.c
index fa6f552..5014005 100644
--- a/src/shine_stubs.c
+++ b/src/shine_stubs.c
@@ -34,7 +34,7 @@
 
 #include <string.h>
 
-#define IS_BIGENDIAN (!*(unsigned char *)&(uint16_t){1})
+#include "config.h"
 
 #ifndef Bytes_val
 #define Bytes_val String_val