FileStorage --> mysql - c++

sorry for my english :) Trying to improve my application I want to copy vectors directly into mysql without string, is it even possible?
FileStorage fs( ".yml", FileStorage::WRITE + FileStorage::MEMORY );
Ptr < FaceRecognizer > model0 = createmyfisherRecognizer();
model0->train( images, labels );
model0->save( fs );
void myfisher::save( FileStorage & fs ) const {
static char * host = "localhost"; /* host serwera MySQL */
static char * user = "root"; /* nazwa loginu by polaczyc sie do serwera */
static char * password = ""; /* haslo */
static char * sql_db = "fisher"; /* nazwa bazy */
static unsigned int sql_port = NULL; /* port na jakim odbiera/wysyla serwer mysql */
static char * opt_socket = NULL; /* socket name */
static unsigned int sql_flags = 0;
static MYSQL * sock; /* Wskaznik do polaczenia do MySQL */
sock = mysql_init( NULL );
if( mysql_real_connect( sock, host, user, password, sql_db, sql_port, opt_socket, sql_flags ) )
cout << "Poprawnie polaczyles sie z baza danych" << endl;
else
cout << "Blad w polaczeniu z baza danych" << endl;
fs << "num_components" << _num_components;
fs << "mean" << _mean;
fs << "eigenvalues" << _eigenvalues;
writeFileNodeList( fs, "projections", _projections );
fs << "labels" << _labels;
string buf = fs.releaseAndGetString();
fs.release();
string zapytanie = "insert into baa values (\"" + buf + "\")";
if( !mysql_query( sock, zapytanie.c_str() ) )
cout << "Poprawnie dodano" << endl;
else
cout << "Blad przy zapisywaniu" << endl;
}
Here I posted the code in question. At the moment it works in this way:
everything is saved into fs (FileStorage)
data in fs is converted to string
fs sent to database
It is known that the program would run much faster if it would be directly copied without the string to the database.

i think you can use snprintf for this, unfortunatelly since there are variable types missing i cant give you exact example.
char string[100];
snprintf(string, 100, "printe text %s,\n and integer %i", "printf", 100); //almost same as printf

Related

deserialization of pod struct stored in redis fails if key is defined as std::string

Storing of POD struct in redis works fine with const char * but doesn't if std::string is involved.
const char * example
#include <hiredis/hiredis.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;
struct Test
{
const uint32_t id;
const char *name;
};
int main() {
redisContext *context = redisConnect("127.0.0.1", 6379);
if (context == NULL || context->err) {
if (context) {
printf("Error: %s\n", context->errstr);
} else {
printf("Can't allocate redis context\n");
}
exit(EXIT_FAILURE);
}
Test obj = {(uint32_t) 123, "foo bar"};
const size_t size = 2 * sizeof(uint32_t) + (strlen(obj.name) + 1);
cout << "object{id: " << obj.id << ", name:' " << obj.name << "'}; size: " << size << endl;
redisReply *reply = 0;
const char *key = strdup("some-key");
reply = (redisReply *) redisCommand(context, "SET %b %b", key, strlen(key), &obj, size);
if (!reply)
return REDIS_ERR;
freeReplyObject(reply);
reply = (redisReply *) redisCommand(context, "GET %s", key);
if (!reply)
return REDIS_ERR;
Test *res = (struct Test*) reply->str;
cout << "result{id: " << res->id << ", name:' " << res->name << "'}; size: " << size << endl;
freeReplyObject(reply);
redisFree(context);
}
If I replace the lines:
const char *key = strdup("some-key");
reply = (redisReply *) redisCommand(context, "SET %b %b", key, strlen(key), &obj, size);
with
std::string key("some-key");
reply = (redisReply *) redisCommand(context, "SET %b %b", key.c_str(), key.size(), &obj, size);
the execution always ends in Segmentation fault.
I can't solve the issue by myself and I would really appreciate any help.
OK, I got it:
replacement of second redisCommand statement
reply = (redisReply *) redisCommand(context, "GET %b", key.c_str(), key.size());
solved the issue.

C++ (Korean) insert error (Incorrect string value)

DB is a C ++ in conjunction with student card management program.
Enter your information to receive a student receives a first input your name and ID. The problem is that there is an error in the insert names.
When directly from MS-DOS window insert (visual studio X)
Hangul (korean) is normal.
(Try the workaround that looked out to the Internet.)
when the insert through a C ++, Hangul (Korean) is not.
hakbun int(50) not null primary key,
name char(100) not null
▲ columns of the table, including information
▲ query status
Source Code
#include "stdio.h"
#include "winsock2.h"
#include "mysql.h"
#include "tchar.h"
#include <iostream>
#include <stdio.h>
using namespace std;
#pragma comment (lib, "libmysql.lib")
const char * host = "localhost";
const char * user = "root";
const char * pw = "1234";
const char * db = "point_db";
void DBconnect () {
 MYSQL * connection = NULL, conn;
 MYSQL_RES * sql_result;
 MYSQL_ROW sql_row;
 mysql_init (& conn);
 connection = mysql_real_connect (& conn, host, user, pw, db, 3306, (char *) NULL, 0);
 if (connection == NULL) {
  printf ( "con error");
 }
 // Mysql_query (connection, "set session character_set_connection = utf-8;");
 // Mysql_query (connection, "set session character_set_results = utf-8;");
 // Mysql_query (connection, "set session character_set_client = utf-8;");
}
int _tmain (int argc, _TCHAR * argv []) {
 
 MYSQL * connection = NULL;
 MYSQL conn;
 MYSQL_RES * sql_result;
 MYSQL_ROW sql_row;
 if (mysql_init (& conn) == NULL) {
  printf ( "mysql_init () error!");
 }
 connection = mysql_real_connect (& conn, host, user, pw, db, 3306, (const char *) NULL, 0);
 if (connection == NULL) {
  printf ( "% d Error:% s,% d \ n", mysql_errno (& conn), mysql_error (& conn));
  return 1;
 }
 else {
  DBconnect ();
  int query_stat;
  char query [1024];
  char num;
  while (1) {
   cout << "+ -------------------- +" << endl;
   cout << "| ① create card |" << Endl;
   cout << "+ -------------------- +" << endl;
   cout << "Enter Number (Played: 0)>";
   cin >> num;
   switch (num) {
   case '1':
    int i, hakbun, student;
    char name [100];
    cout << "student number";
    cin >> hakbun;
    cout << "name";
    cin >> name;
    // Insert
    sprintf_s (query, "insert into point (hakbun, name) values ​​( '% d', '% s')", hakbun, name);
    query_stat = mysql_query (connection, query);
    if (query_stat! = 0) {
     printf ( "error:% s", mysql_error (& conn));
     return 1;
    }
    else {
     cout << "you have completed the creation card." << Endl;
    }
   default:
    cout << "to end the program." << Endl;
    exit (0);
   }
  }
 }
}
my.ini file Detail
[mysqld]
basedir = C:/mysql-5.7.15-winx64
datadir = C:/mysql-5.7.15-winx64/data
port = 3306
# server_id = .....
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#add
character-set-client-handshake = FALSE
init_connect=”SET collation_connection = utf8_general_ci”
init_connect=”SET NAMES utf8″
character-set-server = utf8
[client]
default-character-set = utf8
[mysql]
default-character-set = utf8
[mysqldump]
default-character-set = utf8

How to break C++ program into modules

I'm writing a c++ program that has two functions that can run completely independent one from another. So i want to break them into two programs.
The problem is that both of them rely on the same set of functions (that can grow or change). What i want to do is include this set of functions as a header in both programs so i dont have to copy/paste every time i change something (i also hate duplicating functions or anything).
I know is a silly question but i couldn't find any documentation on the matter.
If the code is necessary ask for it and i will post it.
Thanks!
EDIT:
Adding code:
The functions that can run independent are make_video() and delete_video()
Please have in mind that this is far from done.
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string>
#include <cstring>
#include <dirent.h>
#include <vector>
#include <time.h>
#include <csignal>
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
#include <mysql/mysql.h>
#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
struct config_t{
std::string sql_host; //mysql host
std::string sql_user; //mysql user
std::string sql_pass; //mysql password
std::string sql_db; //zoneminder database name
std::string sql_ev_zm; //zoneminder events table
std::string sql_ev_vid; //video events table
std::string sql_ev_videxp; //video events expiration table
std::string sql_mon; //zm monitors table
std::string dir_ev; //Zoneminder events directory
std::string dir_vid; //manager videos directory
std::string dir_ram; //Ramfs mount directory
std::string ram_size; //ramfs size
};
int is_dir(const char *pathname){
struct stat info;
if( stat( pathname, &info ) != 0 )
return -1;
else if( info.st_mode & S_IFDIR ) // S_ISDIR() doesn't exist on my windows
return 1;
else
return 0;
}
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrimmed(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrimmed(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trimmed(std::string s) {
trim(s);
return s;
}
bool DirectoryExists ( const char* path ){
if( path == NULL )return false;
DIR *d;
d = opendir(path);
if (d){
closedir(d);
return true;
}
return false;
}
std::ifstream::pos_type filesize(const char* filename){
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return in.tellg();
}
bool mount_ramfs(config_t *conf){
return false;
}
bool make_video(config_t *conf, std::string path = "", int depth = 0){
try{
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass);
stmt = con->createStatement();
stmt->execute("USE " + conf->sql_db);
std::string query = "SELECT Id, MonitorId, StartTime, EndTime, Length, Frames FROM " + conf->sql_ev_zm + " WHERE EndTime IS NOT NULL LIMIT 10"; //select a bunch of events for processing, EndTime NOT NULL means that the event is complete and not corrupted
//syslog (LOG_DEBUG, "Mysql Query: %s", query.c_str());
res = stmt->executeQuery(query);
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() - INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE "%2015-11-18%" and MonitorId = 56
// conf.dir_ev + "/" + MonitorId + "/" + todir(StartTime)
while (res->next()) {
int id = res->getInt("Id");
int monitor = res->getInt("MonitorId");
std::string start_time = res->getString("StartTime");
std::string end_time = res->getString("EndTime");
int lenght = res->getInt("Length");
int frames = res->getInt("Frames");
//Get event directory form table data; the dir structure is id/YY/MM/DD/HH/mm/ss/
char sttm[60] = {};
std::strcpy(sttm, start_time.c_str());
char * tkn = (char*)malloc(60);
std::stringstream pathSS;
pathSS << conf->dir_ev << '/' << id << '/'; //prepare the path
tkn = std::strtok (sttm," -:"); //here we tokenize the StartTime field to match the source directory structure
if (tkn != NULL) {
pathSS << tkn[2] << tkn[3] << '/';
tkn = std::strtok (NULL, " -:");
}
while (tkn != NULL) {
pathSS << tkn << '/';
tkn = std::strtok (NULL, " -:");
}
std::string src = pathSS.str();
pathSS.clear();
pathSS << conf->dir_vid << '/' << id << '/'; //prepare the path
std::string dest = pathSS.str();
pathSS.clear();
tkn = std::strtok (sttm," -:"); //here we tokenize the StartTime field to make the destinantion and filename
while (tkn != NULL) {
pathSS << tkn << '_'; //sadly this will always lead to "_.mp4" but its not that bad or important
tkn = std::strtok (NULL, " -:");
}
pathSS << ".mp4";
std::string fname = pathSS.str();
pathSS.clear();
//do event video and
/*std::string cmd = "mkdir -p " + conf->dir_vid + path;
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
cmd = "tar -zcf " + conf->dir_vid + path + "/" + dirlist[i] +".tar.gz " + conf->dir_ev + path + "/" + dirlist[i];
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
cmd = "rm -rf " + conf->dir_ev + src + "*";
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());*/
try{
//insert new row in videos table
pathSS << "INSERT INTO " << conf->sql_ev_vid << " (startTime, endTime, monitor, filename) VALUES (\'" << start_time << "\', \'" << end_time << "\', " << monitor << ",\'" << dest << fname << "\')";
stmt->execute(pathSS.str());
pathSS.clear();
//delete non existing event
pathSS << "DELETE FROM " << conf->sql_ev_zm << " WHERE Id = " << id;
stmt->execute(pathSS.str());
pathSS.clear();
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
}
delete res;
delete stmt;
delete con;
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
return true;
}
bool delete_video(config_t *conf){
try{
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
sql::ResultSet *subres;
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass);
stmt = con->createStatement();
stmt->execute("USE " + conf->sql_db);
std::string query = "SELECT monitor, recording_days FROM " + conf->sql_ev_videxp + " WHERE 1";
//syslog (LOG_DEBUG, "Mysql Query: %s", query.c_str());
res = stmt->executeQuery(query);
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() - INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE "%2015-11-18%" and MonitorId = 56
// conf.dir_ev + "/" + MonitorId + "/" + todir(StartTime)
while (res->next()) {
int id = res->getInt("Id");
int r_days = res->getInt("recording_days");
//syslog (LOG_DEBUG, "Id: %i, Recording Days: %i", id, r_days);
std::stringstream subQuerySS;
subQuerySS << "SELECT id, file FROM " << conf->sql_ev_vid << " WHERE date < NOW() - INTERVAL " << r_days << " DAY AND monitor = " << id;
std::string subQuery = subQuerySS.str();
subQuerySS.clear();
//syslog (LOG_DEBUG, "Mysql Query: %s", subQuery.c_str());
subres = stmt->executeQuery(subQuery);
while (subres->next()) {
int subid = subres->getInt("id");
std::string file = subres->getString("file");
std::string cmd = "rm -f " + file;
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
std::stringstream delQuerySS;
delQuerySS << "DELETE FROM " << conf->sql_ev_vid << " WHERE id = " << subid;
std::string delQuery = delQuerySS.str();
delQuerySS.clear();
syslog (LOG_DEBUG, "Mysql Query: %s", delQuery.c_str());
stmt->execute(delQuery);
}
}
delete res;
delete subres;
delete stmt;
delete con;
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
return true;
}
void signalHandler( int signum ){
syslog (LOG_NOTICE, "signal received (%i)", signum);
closelog();
exit(signum);
}
int main(void) {
/* Our process ID and Session ID */
pid_t pid, sid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
std::ofstream pid_file;
pid_file.open("evmanager.pid", std::ofstream::trunc);
if( pid_file.is_open()){
pid_file << pid;
pid_file.close();
}
exit(EXIT_SUCCESS);
}
/* Change the file mode mask */
umask(0);
setlogmask (LOG_UPTO (LOG_DEBUG));
openlog ("dt_event_manager", LOG_PID, LOG_DAEMON);
syslog (LOG_NOTICE, "Program started by User %d", getuid ());
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
syslog (LOG_ERR, "SID Creation Failed");
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
syslog (LOG_ERR, "Failed while Changing directory to /");
exit(EXIT_FAILURE);
}
/* Read Initial Configuration */
std::ifstream conf_file;
std::string line;
config_t conf;
conf_file.open("/etc/zm/evmanager.conf");
if( conf_file.is_open()){
while( std::getline(conf_file, line) ){
if(line[0] == '#')continue;
std::istringstream is_line(line);
std::string key;
if( std::getline(is_line, key, '=') ){
std::string value;
if( std::getline(is_line, value) ){
trim(key);
trim(value);
if( key == "sql_host" )conf.sql_host = value; //mysql host
else if( key == "sql_user" )conf.sql_user = value; //mysql user
else if( key == "sql_pass" )conf.sql_pass = value; //mysql password
else if( key == "sql_db")conf.sql_db = value; //zoneminder database name
else if( key == "sql_ev_zm" )conf.sql_ev_zm = value; //zoneminder events table
else if( key == "sql_ev_vid" )conf.sql_ev_vid = value; //video events table
else if( key == "sql_ev_videxp" )conf.sql_ev_videxp = value; //Zoneminder videos expiration directory
else if( key == "sql_mon" )conf.sql_mon = value; //Zoneminder Monitors directory
else if( key == "dir_ev" )conf.dir_ev = value; //Zoneminder events directory
else if( key == "dir_vid" )conf.dir_vid = value; //Manager Videos directory
else if( key == "dir_ram" )conf.dir_ram = value; //Ramfs mount dir
else if( key == "ram_size" )conf.ram_size = value; //Ramfs size
else{
syslog (LOG_ERR, "Bad config readout");
exit(EXIT_FAILURE);
}
}
}
}
}
else{
syslog (LOG_ERR, "Failed to open configuration file");
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Daemon-specific initialization goes here */
/* The Big Loop */
signal(SIGINT, signalHandler);
syslog (LOG_INFO, "Daemon Started");
while (1) {
make_video();
delete_video();
sleep(10); /* wait 10 seconds */
}
exit(EXIT_SUCCESS);
}
This is a great question. I actually solve this issue a lot with students, as I was a C++ tutor.
As an example, let's say if this was your main:
//main.cpp:
#include <iostream>
#include "add.h" /// This comes in later :)
using namespace std;
int main()
{
cout << "2+3=" << add(2,3) << endl;
return 0;
}
You need to create a header file for the add function, like this:
//add.h
#ifndef ADD_H_INCLUDED
#define ADD_H_INCLUDED
int add(int a, int b);
#endif // ADD_H_INCLUDED
But then you need to actually define what the add function actually does:
//add.cpp
#include "add.h"
int add(int a, int b) {
return a + b;
}
Now you can choose to put multiple functions in a single header file, or each function can have its own header file, but it's your choice :) I hope this helps!
You have a number of options. The simplest is to create several files, perhaps like this:
shared_header.hpp
shared_functionality.cpp
prog_a.cpp
prog_b.cpp
Then program A is compiled with sources prog_a.cpp and shared_functionality.cpp, and program B is compiled with sources prog_b.cpp and shared_functionality.cpp. All source files include the header, and prog_a.cpp and prog_b.cpp define their own main function each.

snd_pcm_hw_params_set_period_size_near doesn't return the good value

I'm trying to encalpsulate alsa inside a class.
The problem is when i try to use :
snd_pcm_hw_params_get_period_size(this->__params, &period_size, NULL);
or
snd_pcm_hw_params_get_period_time(this->__params, &time_period, NULL);
inside void alsa_control::record_to_file(std::string filename, int duration_in_us);
in the cpp it send 0 in period and seems to be unmodified for period_time
The .h
#ifndef ALSA_RECORDING_H
#define ALSA_RECORDING_H
#include <iostream>
#include <alsa/asoundlib.h>
#include <wav_functions.h>
#define STEREO 2
#define MONO 1
using std::cout;
using std::endl;
class alsa_control {
public:
void record_to_file(std::string filename, int duration_in_us);
alsa_control(unsigned int rate, unsigned long frames, int bits, unsigned int stereo_mode);
~alsa_control();
private:
unsigned int __rate;
unsigned int __stereo_mode;
int __bits;
snd_pcm_uframes_t __frames;
snd_pcm_hw_params_t *__params;
snd_pcm_t *__handle;
void open_pcm_device();
void set_parameters_ALSA();
alsa_control()=delete;
alsa_control(const alsa_control&)=delete;
};
#endif /* ALSA_RECORDING_H */
and the .cpp
#include <alsa_control.h>
alsa_control::alsa_control(unsigned int rate, unsigned long frames, int bits, unsigned int stereo_mode)
: __rate(rate),
__stereo_mode(stereo_mode),
__bits(bits),
__frames(frames) {
this->open_pcm_device();
snd_pcm_hw_params_alloca(&this->__params);
this->set_parameters_ALSA();
}
alsa_control::~alsa_control() {
snd_pcm_drain(this->__handle);
snd_pcm_close(this->__handle);
}
void alsa_control::open_pcm_device() {
int rc = snd_pcm_open(&this->__handle, "default", SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
cout << "ERROR : unable to open pcm device: " << snd_strerror(rc) << endl;
exit(1);
}
}
void alsa_control::set_parameters_ALSA() {
snd_pcm_hw_params_any(this->__handle, this->__params); // def values
snd_pcm_hw_params_set_access(this->__handle, this->__params, SND_PCM_ACCESS_RW_NONINTERLEAVED); //non interleaved
snd_pcm_hw_params_set_format(this->__handle, this->__params, SND_PCM_FORMAT_S16_LE); //16bits little-endian
snd_pcm_hw_params_set_channels(this->__handle, this->__params, this->__stereo_mode); // stereo ou mono
snd_pcm_hw_params_set_rate_near(this->__handle, this->__params, &this->__rate, NULL); // sample rate (freq echantillonage)
auto ret = snd_pcm_hw_params_set_period_size_near(this->__handle, this->__params, &this->__frames, NULL); //frames pour une période
int rc = snd_pcm_hw_params(this->__handle, this->__params);
if (rc < 0) {
cout << "ERROR - unable to set hw parameters: " << snd_strerror(rc) << endl;
exit(1);
}
}
void alsa_control::record_to_file(std::string filename, int duration_in_us) {
std::ofstream f;
int rc;
int nb_ech = 0;
snd_pcm_uframes_t period_size;
unsigned int time_period;
filename += ".wav";
f.open(filename, std::ios::binary);
write_header_wav(f, this->__rate, (short) this->__bits, (short) this->__stereo_mode, 10000); //10000 is a constant because we don't know the size of the recording
snd_pcm_hw_params_get_period_size(this->__params, &period_size, NULL);
period_size = 2048;
snd_pcm_uframes_t size = period_size * 2; /* 2 bytes/sample, 1 channels */
char *buffer = (char *) malloc(size);
snd_pcm_hw_params_get_period_time(this->__params, &time_period, NULL);
time_period = 128000;
long loops = duration_in_us / time_period;
while (loops-- > 0) {
rc = (int) snd_pcm_readi(this->__handle, buffer, period_size);
if (rc == -EPIPE) {
cout << "ERROR - overrun occurred" << endl;
snd_pcm_prepare(this->__handle);
} else if (rc < 0) {
cout << "ERROR - error from read: " << snd_strerror(rc) << endl;
} else if (rc != (int) period_size) {
cout << "ERROR - short read, read " << rc << " frames" << endl;
}
if (!(loops % 10))cout << loops << endl;
f.write(buffer, rc * 2);
nb_ech += rc;
}
f.close();
f.open(filename, std::ios::binary | std::ios::in);
write_header_wav(f, this->__rate, (short) this->__bits, (short) this->__stereo_mode, nb_ech);
f.close();
free(buffer);
}
I've just figured one way to make it works. But i'm always wondering why the functions don't works correctly.
snd_pcm_hw_params_get_period_size(this->_params, period_size, NULL); and snd_pcm_hw_params_get_period_time(this->_params, time_period, NULL); works fine when inside the set_parameters_ALSA method.
Then i've just added them to my class as private members :
snd_pcm_uframes_t _period_size; and unsigned int _time_period;
And changed the two functions to :
void alsa_control::set_parameters_ALSA() {
snd_pcm_hw_params_any(this->_handle, this->_params); // def values
snd_pcm_hw_params_set_access(this->_handle, this->_params, SND_PCM_ACCESS_RW_NONINTERLEAVED); //non interleaved
snd_pcm_hw_params_set_format(this->_handle, this->_params, SND_PCM_FORMAT_S16_LE); //16bits little-endian
snd_pcm_hw_params_set_channels(this->_handle, this->_params, this->_stereo_mode); // stereo ou mono
snd_pcm_hw_params_set_rate_near(this->_handle, this->_params, &this->_rate, NULL); // sample rate (freq echantillonage)
snd_pcm_hw_params_set_period_size_near(this->_handle, this->_params, &this->_frames, NULL); //frames pour une période
int rc = snd_pcm_hw_params(this->_handle, this->_params);
if (rc < 0) {
cout << "ERROR - unable to set hw parameters: " << snd_strerror(rc) << endl;
exit(1);
}
snd_pcm_hw_params_get_period_size(this->_params, &this->_period_size, NULL);
snd_pcm_hw_params_get_period_time(this->_params, &this->_time_period, NULL);
}
and
void alsa_control::record_to_file(std::string filename, int duration_in_us) {
std::ofstream f;
int rc;
int nb_ech = 0;
filename += ".wav";
f.open(filename, std::ios::binary);
write_header_wav(f, this->_rate, (short) this->_bits, (short) this->_stereo_mode, 10000); //10000 is an arbitrary constant because we don't know the size of the recording
snd_pcm_uframes_t size = this->_period_size * 2; /* 2 bytes/sample, 1 channels */
char *buffer = (char *) malloc(size);
long loops = duration_in_us / this->_time_period;
while (loops-- > 0) {
rc = (int) snd_pcm_readi(this->_handle, buffer, this->_period_size);
if (rc == -EPIPE) {
cout << "ERROR - overrun occurred" << endl;
snd_pcm_prepare(this->_handle);
} else if (rc < 0) {
cout << "ERROR - error from read: " << snd_strerror(rc) << endl;
} else if (rc != (int) this->_period_size) {
cout << "ERROR - short read, read " << rc << " frames" << endl;
}
f.write(buffer, rc * 2);
nb_ech += rc;
}
f.close();
f.open(filename, std::ios::binary | std::ios::in);
write_header_wav(f, this->_rate, (short) this->_bits, (short) this->_stereo_mode, nb_ech);
f.close();
free(buffer);
}
EDIT :
This problem seems to be related to driver.
Using : Advanced Linux Sound Architecture Driver Version k3.16.0-31-generic don't work with the question version
Using : Advanced Linux Sound Architecture Driver Version k3.18.8+ works good

Processing large files with libsndfile

Currently I've written a program (in Visual Studio C++) based on the available example code of "libsndfile" in which I've just added a subtraction-function to subtract one (channel of a) WAV-file with another.
The program worked perfectly for files with a limit of 4 channels.
The problem is that as soon as I upload a file with as many as 5 channels or more, the program refuses to execute the function. This is independent of the frame-size as I've managed to process 4-channel files which were many times larger than some 5/6-channel-files which I have used.
Has anyone encountered this or a similar problem before? If requested I will provide the source code.
My apologies for the bad structure, I don't really optimize until I get the whole deal working.
Code:
#include <sndfile.hh>
#include <tinyxml2.h>
#include <iostream>
#include <fstream>
#define BLOCK_SIZE 32
using TiXmlDocument = tinyxml2::XMLDocument;
using CStdStringA = std::string;
int main(int argc, char* argv[])
{
SNDFILE *infile = NULL;
SNDFILE *infile2 = NULL;
SNDFILE *outfile = NULL;
SF_INFO sfinfo;
SF_INFO sfinfo2;
SF_INFO sfinfoOut;
sf_count_t readcount;
//int filetype = SF_FORMAT_WAV | SF_FORMAT_PCM_24; // 24-bit Wav-Files
TiXmlDocument iDoc; // Init tinyXML
int i; // Iteration-var;
short BufferIn[BLOCK_SIZE]; // Buffer1
short BufferIn2[BLOCK_SIZE]; // Buffer2
short BufferOut[BLOCK_SIZE];
CStdStringA FileLoc, FileName, FileLocWav, FileLocTxt,FileLocRaw; // OutputFile locationstring
CStdStringA WavName, WavName2, FileIn, FileIn2;
FileLoc = "C:\\Testfiles\\";
//TextTitle(FileLoc); // Print console-header
printf("Name Wavefile 1:\n");
std::cin >> WavName;
FileIn = FileLoc + WavName + ".wav";
if((infile = sf_open(FileIn.c_str(),SFM_READ,&sfinfo)) == NULL) // Open Wav-file 2 instance
{
printf("Not able to open input file 1\n");
printf("\n\nPress any key to exit."); // Exit-text if file not present
puts(sf_strerror(NULL)) ;
return 1;
}
std::cout << "Wav file 1 succesfully opened." << std::endl;
std::cout << "\nChannels: " << sfinfo.channels << "\nFrames: " << sfinfo.frames << std::endl; // Print Channels & Frames
std::cout << "Samplerate: " << sfinfo.samplerate << "\n\n" << std::endl;// Print Samplerate
printf("Name Wavefile 2:\n");
std::cin >> WavName2;
FileIn2 = FileLoc + WavName2 + ".wav";
if((infile2 = sf_open(FileIn2.c_str(),SFM_READ,&sfinfo2)) == NULL) // Open Wav-file 2 instance
{
printf("Not able to open input file 2\n");
printf("\n\nPress any key to exit."); // Exit-text if file not present
puts(sf_strerror(NULL)) ;
return 1;
}
std::cout << "Wav file 2 succesfully opened." << std::endl;
std::cout << "\nChannels: " << sfinfo2.channels << "\nFrames: " << sfinfo2.frames << std::endl; // Print Channels & Frames
std::cout << "Samplerate: " << sfinfo2.samplerate << "\n\n" << std::endl;// Print Samplerate
//{
//std::cout << "Format differs from eachother, abort program.";
//printf("\n\nPress any key to exit."); // Exit-text
//return 1;
//}
if(sfinfo.channels != sfinfo2.channels) // Abort if channels not the same
{
std::cout << "Channelammount differs from eachother, abort program.";
printf("\n\nPress any key to exit."); // Exit-text
return 1;
}
if(sfinfo.samplerate != sfinfo2.samplerate) // Abort if samplerate not the same
{
std::cout << "Samplerate differs from eachother, abort program.";
printf("\n\nPress any key to exit."); // Exit-text
return 1;
}
std::cout << "Give a filename for Txt- & Wav-file: ";
std::cin >> FileName;
FileLoc += FileName; // Fuse Filelocation with given name
FileLocTxt = FileLoc + ".txt";
FileLocWav = FileLoc + ".wav";
FileLocRaw = FileLoc + "Raw.txt";
sfinfoOut.channels = sfinfo.channels;
sfinfoOut.format = sfinfo.format;
sfinfoOut.samplerate = sfinfo.samplerate;
if((outfile = sf_open(FileLocWav.c_str(),SFM_WRITE,&sfinfoOut)) == NULL) // Open Wav-file 2 instance
{
printf("Not able to create output file \n");
printf("\n\nPress any key to exit."); // Exit-text if file not present
puts(sf_strerror(NULL)) ;
return 1;
}
std::ofstream myfile;
myfile.open(FileLocTxt.c_str(),std::ios::app);
std::ofstream myfileRaw;
myfileRaw.open(FileLocRaw.c_str(),std::ios::app);
while((readcount = sf_read_short(infile, BufferIn, BLOCK_SIZE))) // While there are still frames to be processed
{
//process_data (data, readcount, sfinfo.channels) ;
auto readcount2 = sf_read_short(infile2, BufferIn2, BLOCK_SIZE);
for(i = 0; i < BLOCK_SIZE; i++) // BLOCK_SIZE decides the chunk-size
{
BufferOut[i] = BufferIn[i] - BufferIn2[i];
myfileRaw << BufferOut[i];
}
sf_write_short(outfile, BufferOut, BLOCK_SIZE) ; // Write the data to a new file
}
sf_close(infile); // Close Wav-file handlers
sf_close(infile2);
sf_close(outfile);
myfile.close(); // Close text-file handlers
printf("\n\nPress any key to exit."); // Exit-text
return 0;
}
The documentation states:
File Read Functions (Items)
sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
The file read items functions fill the array pointed to by ptr with the requested number of items. The items parameter must be an integer product of the number of channels or an error will occur
There's your problem, since BLOCK_SIZE is a multiple of 1,2,4 but not of 3 and 5 - so that would fail.
About the problem that program completes as if calculations had taken place: add appropriate error handling.