Images, soundfiles, and SQL image

G

Guest

I have an application that allows users to view images and hear sound files.
The images and soundclips are stores in a SQL database in image fields.
Originally, I transferred the data from an Access database using the Upsize
wizard. I have been able to retrieve the data from the SQL database using
memorystreams. To do so, I have been using offests to bypass a header that is
present: for the images, I use offest 78 and for the sounds, it's 86.

All has been well and good but now I need to load images and sound clips
directly using my app, not Access. I have tried uploading the files using no
offset and/or the offsets I have previously needed to use, all to no avail.
For instance, after I store a .wav file to the database, I receive a message
"The wave header is corrupt".

Now, I see all kinds of examples to store and retrieve blob data on the
internet. None of them deal with headers.

Can anyone clear up this mystery? I am using VS 2005 Express C# edition and
SQL Express 2005.

Code examples:

public void PlaySound()
{
if (ds.Tables["Cards"] != null)
{
if (isSound)
{
sqlConn.Open();
SqlDataAdapter sql = new SqlDataAdapter(
"SELECT Sound FROM Sounds WHERE Sounds.CardID=" +

ds.Tables["Cards"].Rows[curMgr.Position]["CardID"].ToString(),
sqlConn);
DataTable dt = new DataTable();
sql.Fill(dt);
sqlConn.Close();
DataRow dr = dt.Rows[0];

byte[] result = (byte[])dr["Sound"];

try
{
// Retrieve the sound file using the header offset
(86)
MemoryStream ms = new MemoryStream(result,
SNDHDROFFSET, result.Length - SNDHDROFFSET);
SoundPlayer sp = new SoundPlayer(ms);
sp.Play();
}
catch (Exception e)
{
MessageBox.Show("Sound header error! The sound clip
is not properly formatted in the SQL database. "+ e.Message);
}
}
}
}
}


public void AddSound(string soundFilename)
{
SqlCommand cmd = new SqlCommand();
FileStream stream = new FileStream(soundFilename, FileMode.Open,
FileAccess.Read);
byte[] snd = new byte[stream.Length];
stream.Read(snd, 0, (int)stream.Length);
stream.Close();

sqlConn.Open();
if (!isSound)
cmd = new SqlCommand("InsertSound", sqlConn);
else
cmd = new SqlCommand("UpdateSound", sqlConn);
cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("@CardID", SqlDbType.Int).Value =
ds.Tables["Cards"].Rows[curMgr.Position]["CardID"];
cmd.Parameters.Add("@Sound", SqlDbType.Image).Value = snd;
cmd.ExecuteNonQuery();
sqlConn.Close();
isSound = true;
}


ALTER PROCEDURE dbo.InsertSound
(
@CardID int,
@Sound image
)
AS
INSERT INTO Sounds (CardID, Sound)
VALUES (@CardID, @Sound)
RETURN
 
G

Guest

Your assumption here that the header for a WAV sound file is either 78 or 86
bytes is incorrect. WAV headers are typically 44 bytes. In addition, you
would still need the WAV header to be intact in order to play the sound using
the WaveOut Windows API, unless you were to play it as RAW PCM Data at a
fixed sampling rate and channel(s).
--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com




wschlichtman said:
I have an application that allows users to view images and hear sound files.
The images and soundclips are stores in a SQL database in image fields.
Originally, I transferred the data from an Access database using the Upsize
wizard. I have been able to retrieve the data from the SQL database using
memorystreams. To do so, I have been using offests to bypass a header that is
present: for the images, I use offest 78 and for the sounds, it's 86.

All has been well and good but now I need to load images and sound clips
directly using my app, not Access. I have tried uploading the files using no
offset and/or the offsets I have previously needed to use, all to no avail.
For instance, after I store a .wav file to the database, I receive a message
"The wave header is corrupt".

Now, I see all kinds of examples to store and retrieve blob data on the
internet. None of them deal with headers.

Can anyone clear up this mystery? I am using VS 2005 Express C# edition and
SQL Express 2005.

Code examples:

public void PlaySound()
{
if (ds.Tables["Cards"] != null)
{
if (isSound)
{
sqlConn.Open();
SqlDataAdapter sql = new SqlDataAdapter(
"SELECT Sound FROM Sounds WHERE Sounds.CardID=" +

ds.Tables["Cards"].Rows[curMgr.Position]["CardID"].ToString(),
sqlConn);
DataTable dt = new DataTable();
sql.Fill(dt);
sqlConn.Close();
DataRow dr = dt.Rows[0];

byte[] result = (byte[])dr["Sound"];

try
{
// Retrieve the sound file using the header offset
(86)
MemoryStream ms = new MemoryStream(result,
SNDHDROFFSET, result.Length - SNDHDROFFSET);
SoundPlayer sp = new SoundPlayer(ms);
sp.Play();
}
catch (Exception e)
{
MessageBox.Show("Sound header error! The sound clip
is not properly formatted in the SQL database. "+ e.Message);
}
}
}
}
}


public void AddSound(string soundFilename)
{
SqlCommand cmd = new SqlCommand();
FileStream stream = new FileStream(soundFilename, FileMode.Open,
FileAccess.Read);
byte[] snd = new byte[stream.Length];
stream.Read(snd, 0, (int)stream.Length);
stream.Close();

sqlConn.Open();
if (!isSound)
cmd = new SqlCommand("InsertSound", sqlConn);
else
cmd = new SqlCommand("UpdateSound", sqlConn);
cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("@CardID", SqlDbType.Int).Value =
ds.Tables["Cards"].Rows[curMgr.Position]["CardID"];
cmd.Parameters.Add("@Sound", SqlDbType.Image).Value = snd;
cmd.ExecuteNonQuery();
sqlConn.Close();
isSound = true;
}


ALTER PROCEDURE dbo.InsertSound
(
@CardID int,
@Sound image
)
AS
INSERT INTO Sounds (CardID, Sound)
VALUES (@CardID, @Sound)
RETURN
 
G

Guest

Actually, the header information I have (86 bytes) is correct. I am using,
and have been using, the System.Media.SoundPlayer class to play the file from
a database image field. It works perfectly. Attempting to use any other
offest other than 86 throws an exception with an invalid header.

I am not using the WaveOut API as there is no longer a need to do so since
the latest .NET class library includes replacement functionality.
 
G

Guest

Ok. In that case what I would do is retrieve on of these sound files from
your database image field, and save it on the filesystem with a .Wav
extension. Then attempt to play it using your application.

If it doesn't play, you have more information about where and what is going
wrong.
Cheers,
Peter
--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com
 
G

Guest

Yep, it works if I retrieve the soundclips that I upsized from Access. Here's
the code:

sqlConn.Open();
SqlDataAdapter sql = new SqlDataAdapter(
"SELECT Sound FROM Sounds WHERE Sounds.CardID=" +

ds.Tables["Cards"].Rows[curMgr.Position]["CardID"].ToString(),
sqlConn);
DataTable dt = new DataTable();
sql.Fill(dt);
sqlConn.Close();
DataRow dr = dt.Rows[0];

byte[] result = (byte[])dr["Sound"];

try
{
// Retrieve the sound file using the header offset
(86)
using (MemoryStream ms = new MemoryStream(result,
SNDHDROFFSET, result.Length - SNDHDROFFSET))
{
// Test that sound file offest is correct
using (FileStream fs = new
FileStream("c:\\test.wav", FileMode.Create))
{
fs.Write(result, SNDHDROFFSET, result.Length
- SNDHDROFFSET);
}
SoundPlayer sp = new SoundPlayer(ms);
sp.Play();
}
}
catch (Exception e)
{
MessageBox.Show("Sound header error! The sound clip
is not properly formatted in the SQL database. "+ e.Message);
}

The constant SNDHDROFFSET is set to 86. The soundclip sounds exactly the
same using either the sp.Play() method or by using MS Media Player.

Any ideas?
 
G

Guest

As a followup, I believe my problem may be in the stored procedure I posted
in my original message. I am very noobish to SQL, esp. in stored procedures,
and think maybe I'm supposed to be referring to READTEXT or textptr(), but am
not sure. As it stands, I pass the byte[] buffer in one of the parameters to
the INSERT/UPDATE commands in my code. I do no other processing. Am I correct
in assuming this may be where the problem lies?

The reason I deduce this is that when I look at the hex representation of
the stored data as opposed to the original sound clip file, they are nothing
alike.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top