I'm trying to read a .wav file that I have from my .cpp file that I have in my iOS Xcode project. I have searched and I can't find the answer to why it is not reading it well. I putted in all the possible directories and still doesn't work. This is the code that is calling the .wav file:
#define EXPORT __attribute__((visibility("default")))
EXPORT
string getAudioWmark()
{
std::string result;
result = get_watermark("piano2.wav", "");
return (result.c_str());
}
get_watermark method (from wget.cc):
std::string get_watermark (const string& infile, const string& orig_pattern)
{
std::string patterns;
WavData wav_data;
Error err = wav_data.load (infile);
if (err)
{
error ("audiowmark: error loading %s: %s\n", infile.c_str(), err.message());
return "1";
}
if (Params::test_truncate)
{
const size_t want_n_samples = wav_data.sample_rate() * wav_data.n_channels() * Params::test_truncate;
vector<float> short_samples = wav_data.samples();
if (want_n_samples < short_samples.size())
{
short_samples.resize (want_n_samples);
wav_data.set_samples (short_samples);
}
}
int result;
if (wav_data.sample_rate() == Params::mark_sample_rate)
{
result = decode_and_report (wav_data, orig_pattern);
if (PatternStorage::getInstance().getPatterns() != "") {
patterns = PatternStorage::getInstance().getPatterns();
}
return patterns;
}
else
{
result = decode_and_report (resample (wav_data, Params::mark_sample_rate), orig_pattern);
if (PatternStorage::getInstance().getPatterns() != "") {
patterns = PatternStorage::getInstance().getPatterns();
}
return patterns;
}
}
Here is the directories from my Xcode project (the code above is from native-lib.cpp:
Related
I`m trying to parallelize reading and processing archives, that are already in memory, but I get data race while calling libarchive function in a thread. Google sanitizer says that problem is in calling archive_read_open_memory function inside get_archive_contens. But I read that all functions in libarchive should be thread-safe. Can anyone tell me what I did wrong?
Here is my thread code.
void indexing_thread(std::mutex &m,
int ¤t_indexing_threads, concurrent_queue<std::pair<std::string, std::string>> &raw_files_q,
concurrent_queue<std::map<std::string, size_t>> &words_q) {
while (true) {
auto raw_file = raw_files_q.front();
std::string file_buffer = raw_file.first;
std::string ext = raw_file.second;
if (file_buffer.empty() && ext.empty()) {
break;
}
raw_files_q.pop();
std::string file_content;
if (ext == ".zip") {
auto archive_contents = get_archive_content(file_buffer);
for (int i = 0; i < archive_contents.size(); ++i) {
auto cur_ext = boost::filesystem::extension(archive_contents[i]);
if (cur_ext == ".txt") {
file_content = get_archive_file_contents(archive_contents[i], archive_contents, file_buffer);
file_content = convert_to_normalized_utf_string(file_content);
}
}
for (int i = 0; i < archive_contents.size(); ++i) {
auto cur_ext = boost::filesystem::extension(archive_contents[i]);
if (cur_ext == ".txt") {
file_content = get_archive_file_contents(archive_contents[i], archive_contents, file_buffer);
file_content = convert_to_normalized_utf_string(file_content);
}
}
}
auto words = word_count_map_nonparallel(file_content);
words_q.push_back(words);
}
m.lock();
current_indexing_threads--;
if (current_indexing_threads == 0) {
words_q.push_back(std::map<std::string, size_t>{});
}
m.unlock();
}
get_archive_content code:
std::string
get_archive_file_contents(const std::string &filename, std::vector<std::string> contents, std::string file_buffer) {
if (std::find(contents.begin(), contents.end(), filename) == contents.end()) {
throw FileDoesNotExistsException(filename);
}
struct archive_entry *entry;
struct archive *archive = archive_read_new();
archive_read_support_filter_all(archive);
archive_read_support_format_all(archive);
archive_read_support_format_raw(archive);
archive_read_support_format_empty(archive);
int reading_result = archive_read_open_memory(archive, file_buffer.data(), file_buffer.size());
if (reading_result != 0) {
throw std::runtime_error("Error reading archive");
}
void *buf;
int64_t length;
while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
if (archive_entry_filetype(entry) == AE_IFREG) {
length = archive_entry_size(entry);
buf = malloc(length);
if (!buf) {
archive_read_data_skip(archive);
continue;
}
archive_read_data(archive, buf, length);
break;
}
}
std::string result = static_cast<char *>(buf);
return result;
}
UPD: Google thread sanitizer report
I worked it out. The problem was in binary, that gets installed from ubuntu repositories. I solved this problem install libarchive from the sources.
I'm trying to store some hex color palettes in the ESP8266's SPIFFS but when I try to retrieve them I get some weird chars. The code and the log output are below:
Code (ino file):
#include "FS.h" // https://github.com/esp8266/Arduino/
#include <JsonParser.h> // https://github.com/henrikekblad/ArduinoJson
#include <JsonGenerator.h> // https://github.com/henrikekblad/ArduinoJson
using namespace ArduinoJson;
void setup(void) {
Serial.begin(9600);
SPIFFS.format();
SPIFFS.begin();
writeTxtFile("/palettes/warm.json", "[\"ffffff\",\"ed1414\",\"f6f336\",\"ff7e15\"]");
writeTxtFile("/palettes/pastel.json", "[\"ffffff\",\"ff7b7b\",\"8fff70\",\"7878ff\"]");
readPalettes();
}
void loop(void) {
}
bool readPalettes(void) {
bool succeeded = true;
Dir dir = SPIFFS.openDir("/palettes");
while (dir.next()) {
File palette = dir.openFile("r");
if (!readFile(palette, loadPaletteJson)) succeeded = false;
palette.close();
yield();
}
return succeeded;
}
bool loadPaletteJson(char* json, String fileName) {
Serial.print(fileName);Serial.print(F(": "));Serial.println(json);
Parser::JsonParser<5> parser; // one palette is 1+4*1=5 tokens
Parser::JsonArray p = parser.parseArray(json);
if (p.success()) {
//Store the palettes in a vector using a specific structure
return true;
} else {
Serial.println(F("JSON parsing failed"));
}
return false;
}
bool readFile(File file, std::function<bool (char* json, String fileName)> callback) {
if (file) {
String fileName = file.name();
size_t fileSize = file.size();
Serial.print(F("Reading "));Serial.print(fileSize);Serial.print(F(" bytes from "));Serial.println(fileName);
if (fileSize <= 1024) {
char buf[fileSize];
file.readBytes(buf, fileSize);
return callback(buf, getBaseName(fileName));
} else {
Serial.println(F("file size is too large"));
}
} else {
Serial.println(F("file open failed"));
}
return false;
}
String getBaseName(String fileName) {
return fileName.substring(fileName.lastIndexOf('/') + 1, fileName.lastIndexOf('.'));
}
bool writeTxtFile(String path, String content) {
File file = SPIFFS.open(path, "w");
if (file) {
Serial.print(F("Writing content: "));Serial.print(content);Serial.print(F(" to: "));Serial.println(path);
file.print(content);
file.close();
return true;
} else {
Serial.print(F("file open failed: "));Serial.println(path);
}
return false;
}
Arduino's IDE console output:
Writing content: ["ffffff","ed1414","f6f336","ff7e15"] to: /palettes/warm.json
Writing content: ["ffffff","ff7b7b","8fff70","7878ff"] to: /palettes/pastel.json
Reading 37 bytes from /palettes/warm.json
warm: ["ffffff","ed1414","f6f336","ff7e15"]⸮?8⸮?tu #
JSON parsing failed
Reading 37 bytes from /palettes/pastel.json
pastel: ["ffffff","ff7b7b","8fff70","7878ff"]⸮?8⸮?tu #
JSON parsing failed
I don't understand why those chars (⸮?8⸮?tu #) are added to a limited sized buffer. I tried to replace my buffer (char buf[fileSize];) with a unique pointer like this: std::unique_ptr<char[]> buf(new char[fileSize]); (in the function readFile) using buf.get() in the next 2 statements but with the exact same result.
Am I missing something?
EDIT:
As #leetibbett mentioned below, I'm writing a String while trying to read bytes. here is the correction for readFile function:
bool readFile(File file, std::function<bool (char* json, String fileName)> callback) {
if (file) {
String fileName = file.name();
size_t fileSize = file.size();
Serial.print(F("Reading "));Serial.print(fileSize);Serial.print(F(" bytes from "));Serial.println(fileName);
if (fileSize <= 1024) {
String content = file.readStringUntil('\n');
return callback((char*)content.c_str(), getBaseName(fileName));
} else {
Serial.println(F("file size is too large"));
}
} else {
Serial.println(F("file open failed"));
}
return false;
}
I found this code snippet for downloading file:
wxURL url(wxT("http://www.example.com/file.txt"));
if(url.GetError()==wxURL_NOERR)
{
wxString htmldata;
wxInputStream *in = url.GetInputStream();
if(in && in->IsOk())
{
wxStringOutputStream html_stream(&htmldata);
in->Read(html_stream);
wxLogMessage(htmldata);
}
delete in;
}
But fistly it just logs content of file and only for text-files. But I need to download *.exe file to execute it later. So I need to adapt this code to work with binary data, and save this data to file on the disk. Too many Streams used here for my understanding what's going on here. Please help.
I have written below code previously...
This will work fine to download binary files in any platforms.
/** START */
// ex) ht tp://mysite.com/mypath.jpg
wxString path = wxT("/mypath.jpg");
wxString server = wxT("mysite.com");
wxHTTP http;
http.SetHeader(_T("Content-type"), contentType);
http.SetTimeout(10);
// wxString imageFilePath = wxT("/tmp/image.jpg");
wxFileOutputStream output(imageFilePath);
wxDataOutputStream store(output);
if (http.Connect(server, 80))
{
wxInputStream *stream;
stream = http.GetInputStream(path);
if (stream == NULL)
{
output.Close();
}
else
{
unsigned char buffer[1024];
int byteRead;
// receive stream
while (!stream->Eof())
{
stream->Read(buffer, sizeof(buffer));
store.Write8(buffer, sizeof(buffer));
byteRead = stream->LastRead();
if (byteRead <= 0)
{
break;
}
}
output.Close();
}
}
else
{
output.Close();
}
FILE.CPP: I am using this file and to use this I have created object "myFile"
/*
SD - a slightly more friendly wrapper for sdfatlib
This library aims to expose a subset of SD card functionality
in the form of a higher level "wrapper" object.
License: GNU General Public License V3
(Because sdfatlib is licensed with this.)
(C) Copyright 2010 SparkFun Electronics
*/
#include <SD.h>
/* for debugging file open/close leaks
uint8_t nfilecount=0;
*/
File::File(SdFile f,
const char *n) {
// oh man you are kidding me, new() doesnt exist? Ok we do it by hand!
_file=(SdFile *)malloc(sizeof(SdFile));
if (_file) {
memcpy(_file, &f, sizeof(SdFile));
strncpy(_name, n, 12);
_name[12]=0;
/* for debugging file open/close leaks
nfilecount++;
Serial.print("Created \"");
Serial.print(n);
Serial.print("\": ");
Serial.println(nfilecount, DEC);
*/
}
}
File::File(void) {
_file=0;
_name[0]=0;
//Serial.print("Created empty file object");
}
File::~File(void) {
// Serial.print("Deleted file object");
}
// returns a pointer to the file name
char *File::name(void) {
return _name;
}
// a directory is a special type of file
boolean File::isDirectory(void) {
return (_file && _file->isDir());
}
size_t File::write(uint8_t val) {
return write(&val, 1);
}
size_t File::write(const uint8_t *buf,
size_t size) {
size_t t;
if (!_file) {
setWriteError();
return 0;
}
_file->clearWriteError();
t=_file->write(buf,
size);
if (_file->getWriteError()) {
setWriteError();
return 0;
}
return t;
}
int File::peek() {
if (! _file) return 0;
int c=_file->read();
if (c !=-1) _file->seekCur(-1);
return c;
}
int File::read() {
if (_file) return _file->read();
return -1;
}
// buffered read for more efficient, high speed reading
int File::read(void *buf,
uint16_t nbyte) {
if (_file) return _file->read(buf, nbyte);
return 0;
}
int File::available() {
if (! _file) return 0;
uint32_t n=size() - position();
return n > 0X7FFF ? 0X7FFF: n;
}
void File::flush() {
if (_file) _file->sync();
}
boolean File::seek(uint32_t pos) {
if (! _file) return false;
return _file->seekSet(pos);
}
uint32_t File::position() {
if (! _file) return -1;
return _file->curPosition();
}
uint32_t File::size() {
if (! _file) return 0;
return _file->fileSize();
}
void File::close() {
if (_file) {
_file->close();
free(_file);
_file=0;
/* for debugging file open/close leaks
nfilecount--;
Serial.print("Deleted ");
Serial.println(nfilecount, DEC);
*/
}
}
File::operator bool() {
if (_file) return _file->isOpen();
return false;
}
I am trying to create a SD card read write package using Simulink. What happens is here is I would take SD.cpp and SD.h and other required files and create a wrapper file which consists of required operation (i.e. reading and writing to SD card) and I am getting the following errors
SDcard_wrapper.cpp: In function 'void SDcard_Update_wrapper(const boolean_T*, real_T*, const uint8_T*, int_T)':
./SDcard_wrapper.cpp:113: error: no match for 'operator=' in 'myFile = SDClass::open(const char*, uint8_t)(((const char*)"test.txt"), 19u)'
C:\Users\Samanth\Documents\MATLAB\newSD-trail/utility/SdFat.h:135: note: candidates are: SdFile& SdFile::operator=(const SdFile&)
./SDcard_wrapper.cpp:123: error: could not convert 'myFile' to 'bool'
Following is the SDcard_wrapper.cpp error locations:
myFile = SD.open("test.txt", FILE_WRITE); //This is the line where I am getting 1st error
if (myFile) // this is the point where I am getting the error: could not convert 'myFile' to 'bool'
{
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
File SDClass::open(const char* filepath, uint8_t mode) {
/*
Open the supplied file path for reading or writing.
The file content can be accessed via the `file` property of
the `SDClass` object--this property is currently
a standard `SdFile` object from `sdfatlib`.
Defaults to read only.
If `write` is true, default action (when `append` is true) is to
append data to the end of the file.
If `append` is false then the file will be truncated first.
If the file does not exist and it is opened for writing the file
will be created.
An attempt to open a file for reading that does not exist is an
error.
*/
int pathidx;
// do the interative search
SdFile parentdir = getParentDir(filepath, &pathidx);
// no more subdirs!
filepath += pathidx;
if (!filepath[0]) {
// it was the directory itself!
return File(parentdir, "/");
}
// Open the file itself
SdFile file;
// failed to open a subdir!
if (!parentdir.isOpen())
return File();
// there is a special case for the Root directory since its a static dir
if (parentdir.isRoot()) {
if (!file.open(SD.root, filepath, mode)) {
// failed to open the file :(
return File();
}
// dont close the root!
} else {
if (!file.open(parentdir, filepath, mode)) {
return File();
}
// close the parent
parentdir.close();
}
if (mode & (O_APPEND | O_WRITE))
file.seekSet(file.fileSize());
return File(file, filepath);
}
class SdFile : public Print // This is the line pointed above in the second error just for information SdFat.h:135: note: candidates are: SdFile& SdFile::operator=(const SdFile&)
{
public:
/** Create an instance of SdFile. */
SdFile(void): type_(FAT_FILE_TYPE_CLOSED) {}
/**
* writeError is set to true if an error occurs during a write().
* Set writeError to false before calling print() and/or write() and check
* for true after calls to print() and/or write().
*/
//bool writeError;
/**
* Cancel unbuffered reads for this file.
* See setUnbufferedRead()
*/
void clearUnbufferedRead(void) {
flags_ &= ~F_FILE_UNBUFFERED_READ;
}
uint8_t close(void);
uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
uint8_t createContiguous(SdFile* dirFile, const char* fileName, uint32_t size);
/** \return The current cluster number for a file or directory. */
uint32_t curCluster(void) const {
return curCluster_;
}
/** \return The current position for a file or directory. */
uint32_t curPosition(void) const {
return curPosition_;
}
static void dateTimeCallback(void(*dateTime)(uint16_t* date, uint16_t* time)) {
dateTime_ = dateTime;
}
/**
* Cancel the date/time callback function.
*/
static void dateTimeCallbackCancel(void) {
// use explicit zero since NULL is not defined for Sanguino
dateTime_ = 0;
}
I'm using Visual Studio 2011 C++ with boost v1.52.0 Just added method to search for file in sub directories and started to get this error on program close:
Unhandled exception at 0x7733E3BE (ntdll.dll) in Platformer.exe: 0xC0000005: Access violation reading location 0x437FEF0C.
FileSystem.h:
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include "boost/filesystem.hpp"
namespace fs=boost::filesystem;
class FileSystem
{
public:
static const std::string GetExePath();
static const std::string GetFullPath(std::string fileName, std::string searchInPath = "");
};
#endif
FileSystem.cpp
#include "FileSystem.h"
const std::string FileSystem::GetExePath()
{
fs::path path = fs::current_path();
return path.string();
}
const std::string FileSystem::GetFullPath(std::string fileName, std::string searchInPath)
{
if(searchInPath == "")
{
searchInPath = GetExePath();
}
fs::directory_iterator end_iter;
for( fs::directory_iterator dir_iter(searchInPath); dir_iter!=end_iter; ++dir_iter)
{
if(fs::is_directory(dir_iter->status()))
{
return GetFullPath(fileName, dir_iter->path().string());
}
else if (fs::is_regular_file(dir_iter->status()))
{
if(dir_iter->path().filename() == fs::path(fileName).filename())
{
return dir_iter->path().string();
}
}
}
return std::string("");
}
And I use it in that way:
std::string imageFullPath = FileSystem::GetFullPath("image.png");
What is wrong with this code? Thanks.
Firstly I didn't mentioned that I was using SDL (Simple DirectMedia Layer) libraries. These libraries were linked using #pragma comment (lib, ...) That causes errors on the application closing. I defined them in Project Properties -> Linker -> Input -> Additional Dependencies section ant the problem was solved.
Secondly GetFullPath method was wrong. Here is the correct one:
const std::string FileSystem::GetFullPath(std::string fileName, std::string searchInPath)
{
std::string result;
if(searchInPath.empty()) {
searchInPath = GetExePath();
}
fs::directory_iterator end_iter;
for( fs::directory_iterator dir_iter(searchInPath); dir_iter!=end_iter; ++dir_iter)
{
if(fs::is_directory(dir_iter->status()))
{
result = GetFullPath(fileName, dir_iter->path().string());
if(!result.empty())
{
break;
}
}
else if (fs::is_regular_file(dir_iter->status()))
{
if(dir_iter->path().filename() == fs::path(fileName).filename())
{
result = dir_iter->path().string();
if(!result.empty())
{
break;
}
}
}
}
return result;
}