@@ -1388,3 +1388,334 @@ template <typename... Args>
13881388inline void free_fields (Args&... fields) {
13891389 (free_field (fields), ...);
13901390}
1391+
1392+
1393+ // —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
1394+ // 📌📌📌 2 D A R R A Y 📌📌📌
1395+ //
1396+ // 2D Array in PSRAM with Bounds-Check, log_e and reset()
1397+ //
1398+ // Beispielaufruf:
1399+ // ps_array2d<int32_t> s_samples; // Standardkonstruktor
1400+ // s_samples.alloc(2, 1152); // Speicher allozieren für [2][1152]
1401+ //
1402+ // int ch = 0; // Beispiel: Kanal 0
1403+ //
1404+ // // Deklaration von pcm1 als Zeiger auf das erste Element der Zeile (ähnlich wie bei samples[ch])
1405+ // int32_t* pcm1;
1406+ //
1407+ // // Zuweisung:
1408+ // pcm1 = s_samples.get_raw_row_ptr(ch);
1409+ //
1410+ // // Du kannst jetzt 'pcm1' verwenden, als wäre es ein int32_t-Array der Größe 1152
1411+ // pcm1[0] = 42;
1412+ // pcm1[1151] = 99;
1413+ //
1414+ // s_samples.reset(); // Speicher manuell freigeben
1415+ //
1416+
1417+ template <typename T>
1418+ class ps_array2d
1419+ {
1420+ public:
1421+ // Standardkonstruktor: Initialisiert die Dimensionen auf 0.
1422+ ps_array2d () : m_dim1(0 ), m_dim2(0 ) {}
1423+
1424+ // Ursprünglicher Konstruktor: Alloziert Speicher direkt bei der Erstellung.
1425+ ps_array2d (size_t dim1, size_t dim2)
1426+ : m_dim1(dim1), m_dim2(dim2)
1427+ {
1428+ alloc_internal (dim1, dim2);
1429+ }
1430+
1431+ // Neue alloc-Methode: Ermöglicht die spätere Allokation des Speichers.
1432+ bool alloc (size_t dim1, size_t dim2) {
1433+ reset ();
1434+ m_dim1 = dim1;
1435+ m_dim2 = dim2;
1436+ return alloc_internal (dim1, dim2);
1437+ }
1438+
1439+ // Überladung für `alloc` ohne Dimensionen, wenn die Dimensionen bereits gesetzt sind
1440+ bool alloc () {
1441+ if (m_dim1 == 0 || m_dim2 == 0 ) {
1442+ log_e (" ps_array2d::alloc() called without dimensions or dimensions are zero." );
1443+ return false ;
1444+ }
1445+ reset ();
1446+ return alloc_internal (m_dim1, m_dim2);
1447+ }
1448+
1449+ // Klammer-Operator für den Zugriff auf einzelne Elemente (Bounds-Check inklusive)
1450+ T &operator ()(size_t i, size_t j)
1451+ {
1452+ if (!m_data.valid ()) {
1453+ log_e (" ps_array2d: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1454+ return m_dummy;
1455+ }
1456+ if (i >= m_dim1 || j >= m_dim2) {
1457+ log_e (" ps_array2d out-of-bounds: (%u,%u) but dims=(%u,%u) [line %d]" ,
1458+ (unsigned )i, (unsigned )j, (unsigned )m_dim1, (unsigned )m_dim2, __LINE__);
1459+ return m_dummy;
1460+ }
1461+ return m_data[i * m_dim2 + j];
1462+ }
1463+
1464+ const T &operator ()(size_t i, size_t j) const
1465+ {
1466+ if (!m_data.valid ()) {
1467+ log_e (" ps_array2d: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1468+ return m_dummy;
1469+ }
1470+ if (i >= m_dim1 || j >= m_dim2) {
1471+ log_e (" ps_array2d out-of-bounds: (%u,%u) but dims=(%u,%u) [line %d]" ,
1472+ (unsigned )i, (unsigned )j, (unsigned )m_dim1, (unsigned )m_dim2, __LINE__);
1473+ return m_dummy;
1474+ }
1475+ return m_data[i * m_dim2 + j];
1476+ }
1477+
1478+ // NEUE METHODE: Gibt einen rohen Zeiger (T*) auf den Beginn einer spezifischen Zeile (row_index) zurück.
1479+ // Dies ist ideal für deinen Fall 'pcm1 = samples[ch];'
1480+ T* get_raw_row_ptr (size_t row_index) {
1481+ if (!m_data.valid ()) {
1482+ log_e (" ps_array2d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1483+ return nullptr ;
1484+ }
1485+ if (row_index >= m_dim1) {
1486+ log_e (" ps_array2d::get_raw_row_ptr: row_index %u out-of-bounds (%u). [line %d]" ,
1487+ (unsigned )row_index, (unsigned )m_dim1, __LINE__);
1488+ return nullptr ;
1489+ }
1490+ return m_data.get () + row_index * m_dim2;
1491+ }
1492+
1493+ const T* get_raw_row_ptr (size_t row_index) const {
1494+ if (!m_data.valid ()) {
1495+ log_e (" ps_array2d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1496+ return nullptr ;
1497+ }
1498+ if (row_index >= m_dim1) {
1499+ log_e (" ps_array2d::get_raw_row_ptr: row_index %u out-of-bounds (%u). [line %d]" ,
1500+ (unsigned )row_index, (unsigned )m_dim1, __LINE__);
1501+ return nullptr ;
1502+ }
1503+ return m_data.get () + row_index * m_dim2;
1504+ }
1505+
1506+ // Gibt true zurück, wenn der Speicher erfolgreich alloziiert wurde
1507+ bool is_allocated () const { return m_data.valid (); }
1508+
1509+ size_t dim1 () const { return m_dim1; }
1510+ size_t dim2 () const { return m_dim2; }
1511+
1512+ // Manuelle Freigabe des Speichers
1513+ void reset () {
1514+ m_data.reset ();
1515+ m_dim1 = 0 ;
1516+ m_dim2 = 0 ;
1517+ }
1518+
1519+ private:
1520+ size_t m_dim1, m_dim2;
1521+ ps_ptr<T> m_data; // Verwaltet den linearen Speicherblock
1522+ static inline T m_dummy{}; // statischer Dummy-Wert
1523+
1524+ // Private Hilfsmethode für die eigentliche Allokationslogik
1525+ bool alloc_internal (size_t dim1, size_t dim2) {
1526+ if (dim1 == 0 || dim2 == 0 ) {
1527+ log_e (" ps_array2d: Cannot allocate with zero dimensions. [line %d]" , __LINE__);
1528+ return false ;
1529+ }
1530+ size_t total_elements = dim1 * dim2;
1531+ m_data.calloc (total_elements, " ps_array2d_data" );
1532+ if (!m_data.valid ()) {
1533+ log_e (" ps_array2d: Memory allocation failed for %u elements. [line %d]" , (unsigned )total_elements, __LINE__);
1534+ m_dim1 = 0 ; m_dim2 = 0 ;
1535+ return false ;
1536+ }
1537+ return true ;
1538+ }
1539+ };
1540+
1541+ // —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
1542+ // psram_unique_ptr.hpp (Auszug mit ps_array3d)
1543+ //
1544+ // 📌📌📌 3 D A R R A Y 📌📌📌
1545+ //
1546+ // 3D Array in PSRAM with Bounds-Check, log_e and reset()
1547+ //
1548+ // Beispielaufruf:
1549+ // ps_array3d<int32_t> s_sbsample;
1550+ // s_sbsample.alloc(2, 36, 32);
1551+ //
1552+ // int ch = 0; // Beispiel für die erste Dimension
1553+ // int gr = 0; // Beispiel für den Gruppen-Index
1554+ //
1555+ // // Deklaration des C-Stil-Zeigers auf ein 1D-Array [32]
1556+ // int32_t (*sample)[32];
1557+ //
1558+ // // Zuweisung mithilfe der neuen Methode get_raw_row_ptr und dem passenden reinterpret_cast
1559+ // sample = reinterpret_cast<int32_t(*)[32]>(s_sbsample.get_raw_row_ptr(ch, 18 * gr));
1560+ //
1561+ // // Jetzt kannst du 'sample' verwenden:
1562+ // (*sample)[0] = 10;
1563+ //
1564+ // s_sbsample.reset();
1565+ //
1566+
1567+
1568+ template <typename T>
1569+ class ps_array3d {
1570+ public:
1571+ // Standardkonstruktor
1572+ ps_array3d () : m_dim1(0 ), m_dim2(0 ), m_dim3(0 ) {}
1573+
1574+ // Ursprünglicher Konstruktor
1575+ ps_array3d (size_t dim1, size_t dim2, size_t dim3)
1576+ : m_dim1(dim1), m_dim2(dim2), m_dim3(dim3)
1577+ {
1578+ alloc_internal (dim1, dim2, dim3);
1579+ }
1580+
1581+ // alloc-Methode
1582+ bool alloc (size_t dim1, size_t dim2, size_t dim3) {
1583+ reset ();
1584+ m_dim1 = dim1;
1585+ m_dim2 = dim2;
1586+ m_dim3 = dim3;
1587+ return alloc_internal (dim1, dim2, dim3);
1588+ }
1589+
1590+ // Überladung für `alloc` ohne Dimensionen
1591+ bool alloc () {
1592+ if (m_dim1 == 0 || m_dim2 == 0 || m_dim3 == 0 ) {
1593+ log_e (" ps_array3d::alloc() called without dimensions or dimensions are zero." );
1594+ return false ;
1595+ }
1596+ reset ();
1597+ return alloc_internal (m_dim1, m_dim2, m_dim3);
1598+ }
1599+
1600+ // Klammer-Operator für den Zugriff auf einzelne Elemente
1601+ T &operator ()(size_t i, size_t j, size_t k)
1602+ {
1603+ if (!m_data.valid ()) {
1604+ log_e (" ps_array3d: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1605+ return m_dummy;
1606+ }
1607+ if (i >= m_dim1 || j >= m_dim2 || k >= m_dim3) {
1608+ log_e (" ps_array3d out-of-bounds: (%u,%u,%u) but dims=(%u,%u,%u) [line %d]" ,
1609+ (unsigned )i, (unsigned )j, (unsigned )k,
1610+ (unsigned )m_dim1, (unsigned )m_dim2, (unsigned )m_dim3, __LINE__);
1611+ return m_dummy;
1612+ }
1613+ return m_data[i * (m_dim2 * m_dim3) + j * m_dim3 + k];
1614+ }
1615+
1616+ const T &operator ()(size_t i, size_t j, size_t k) const
1617+ {
1618+ if (!m_data.valid ()) {
1619+ log_e (" ps_array3d: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1620+ return m_dummy;
1621+ }
1622+ if (i >= m_dim1 || j >= m_dim2 || k >= m_dim3) {
1623+ log_e (" ps_array3d out-of-bounds: (%u,%u,%u) but dims=(%u,%u,%u) [line %d]" ,
1624+ (unsigned )i, (unsigned )j, (unsigned )k,
1625+ (unsigned )m_dim1, (unsigned )m_dim2, (unsigned )m_dim3, __LINE__);
1626+ return m_dummy;
1627+ }
1628+ return m_data[i * (m_dim2 * m_dim3) + j * m_dim3 + k];
1629+ }
1630+
1631+ // Methode zum Abrufen eines rohen Zeigers auf den Beginn eines 2D-Slices.
1632+ T* get_raw_slice_ptr (size_t i) {
1633+ if (!m_data.valid ()) {
1634+ log_e (" ps_array3d::get_raw_slice_ptr: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1635+ return nullptr ;
1636+ }
1637+ if (i >= m_dim1) {
1638+ log_e (" ps_array3d::get_raw_slice_ptr: dim1 index %u out-of-bounds (%u). [line %d]" , (unsigned )i, (unsigned )m_dim1, __LINE__);
1639+ return nullptr ;
1640+ }
1641+ return m_data.get () + i * (m_dim2 * m_dim3);
1642+ }
1643+
1644+ const T* get_raw_slice_ptr (size_t i) const {
1645+ if (!m_data.valid ()) {
1646+ log_e (" ps_array3d::get_raw_slice_ptr: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1647+ return nullptr ;
1648+ }
1649+ if (i >= m_dim1) {
1650+ log_e (" ps_array3d::get_raw_slice_ptr: dim1 index %u out-of-bounds (%u). [line %d]" , (unsigned )i, (unsigned )m_dim1, __LINE__);
1651+ return nullptr ;
1652+ }
1653+ return m_data.get () + i * (m_dim2 * m_dim3);
1654+ }
1655+
1656+ // NEUE METHODE: Gibt einen rohen Zeiger (T*) auf den Beginn einer spezifischen Zeile (dim2_idx)
1657+ // innerhalb eines spezifischen Slices (dim1_idx) zurück.
1658+ T* get_raw_row_ptr (size_t dim1_idx, size_t dim2_idx) {
1659+ if (!m_data.valid ()) {
1660+ log_e (" ps_array3d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1661+ return nullptr ;
1662+ }
1663+ if (dim1_idx >= m_dim1 || dim2_idx >= m_dim2) {
1664+ log_e (" ps_array3d::get_raw_row_ptr: Indices (%u,%u) out-of-bounds for dims=(%u,%u) [line %d]" ,
1665+ (unsigned )dim1_idx, (unsigned )dim2_idx, (unsigned )m_dim1, (unsigned )m_dim2, __LINE__);
1666+ return nullptr ;
1667+ }
1668+ // Berechne den Offset für die spezifische Zeile im linearen Speicher
1669+ return m_data.get () + (dim1_idx * (m_dim2 * m_dim3)) + (dim2_idx * m_dim3);
1670+ }
1671+
1672+ const T* get_raw_row_ptr (size_t dim1_idx, size_t dim2_idx) const {
1673+ if (!m_data.valid ()) {
1674+ log_e (" ps_array3d::get_raw_row_ptr: Access on unallocated memory. Call alloc() first. [line %d]" , __LINE__);
1675+ return nullptr ;
1676+ }
1677+ if (dim1_idx >= m_dim1 || dim2_idx >= m_dim2) {
1678+ log_e (" ps_array3d::get_raw_row_ptr: Indices (%u,%u) out-of-bounds for dims=(%u,%u) [line %d]" ,
1679+ (unsigned )dim1_idx, (unsigned )dim2_idx, (unsigned )m_dim1, (unsigned )m_dim2, __LINE__);
1680+ return nullptr ;
1681+ }
1682+ return m_data.get () + (dim1_idx * (m_dim2 * m_dim3)) + (dim2_idx * m_dim3);
1683+ }
1684+
1685+
1686+ // Gibt true zurück, wenn der Speicher erfolgreich alloziiert wurde
1687+ bool is_allocated () const { return m_data.valid (); }
1688+
1689+ size_t dim1 () const { return m_dim1; }
1690+ size_t dim2 () const { return m_dim2; }
1691+ size_t dim3 () const { return m_dim3; }
1692+
1693+ // Manuelle Freigabe des Speichers
1694+ void reset () {
1695+ m_data.reset ();
1696+ m_dim1 = 0 ;
1697+ m_dim2 = 0 ;
1698+ m_dim3 = 0 ;
1699+ }
1700+
1701+ private:
1702+ size_t m_dim1, m_dim2, m_dim3;
1703+ ps_ptr<T> m_data; // Verwaltet den linearen Speicherblock
1704+ static inline T m_dummy{}; // Dummy-Wert für Fehlerfälle
1705+
1706+ // Private Hilfsmethode für die eigentliche Allokationslogik
1707+ bool alloc_internal (size_t dim1, size_t dim2, size_t dim3) {
1708+ if (dim1 == 0 || dim2 == 0 || dim3 == 0 ) {
1709+ log_e (" ps_array3d: Cannot allocate with zero dimensions. [line %d]" , __LINE__);
1710+ return false ;
1711+ }
1712+ size_t total_elements = dim1 * dim2 * dim3;
1713+ m_data.calloc (total_elements, " ps_array3d_data" );
1714+ if (!m_data.valid ()) {
1715+ log_e (" ps_array3d: Memory allocation failed for %u elements. [line %d]" , (unsigned )total_elements, __LINE__);
1716+ m_dim1 = 0 ; m_dim2 = 0 ; m_dim3 = 0 ;
1717+ return false ;
1718+ }
1719+ return true ;
1720+ }
1721+ };
0 commit comments